LCOV - code coverage report
Current view: top level - coupling/services - CouplingCellService.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 6 22 27.3 %
Date: 2025-06-25 11:26:37 Functions: 1 6 16.7 %

          Line data    Source code
       1             : // Copyright (C) 2015 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_COUPLINGCELLSERVICE_H_
       6             : #define _MOLECULARDYNAMICS_COUPLING_SERVICES_COUPLINGCELLSERVICE_H_
       7             : 
       8             : #pragma once
       9             : 
      10             : #include "coupling/CouplingCellPlotter.h"
      11             : #include "coupling/KineticEnergyController.h"
      12             : #include "coupling/MomentumController.h"
      13             : #include "coupling/cell-mappings/ComputeMeanPotentialEnergyMapping.h"
      14             : #include "coupling/cell-mappings/ComputeMomentumMapping.h"
      15             : #include "coupling/cell-mappings/PerturbateVelocityMapping.h"
      16             : #include "coupling/configurations/BoundaryForceConfiguration.h"
      17             : #include "coupling/configurations/CouplingCellConfiguration.h"
      18             : #include "coupling/configurations/MaMiCoConfiguration.h"
      19             : #include "coupling/configurations/MomentumInsertionConfiguration.h"
      20             : #include "coupling/configurations/ParallelTopologyConfiguration.h"
      21             : #include "coupling/configurations/ParticleInsertionConfiguration.h"
      22             : #include "coupling/configurations/ThermostatConfiguration.h"
      23             : #include "coupling/configurations/TransferStrategyConfiguration.h"
      24             : #include "coupling/datastructures/CellContainer.h"
      25             : #include "coupling/indexing/IndexingService.h"
      26             : #include "coupling/interface/MDSolverInterface.h"
      27             : #include "coupling/interface/MacroscopicSolverInterface.h"
      28             : #include "coupling/sendrecv/DataExchangeFromMD2Macro.h"
      29             : #include "coupling/sendrecv/DataExchangeFromMacro2MD.h"
      30             : #include "coupling/sendrecv/FromMD2Macro.h"
      31             : #include "coupling/sendrecv/FromMacro2MD.h"
      32             : #include "tarch/utils/MultiMDService.h"
      33             : 
      34             : #include "coupling/filtering/FilterPipeline.h"
      35             : 
      36             : namespace coupling {
      37             : namespace services {
      38             : 
      39             : template <unsigned int dim> class CouplingCellService;
      40             : 
      41             : template <class LinkedCell, unsigned int dim> class CouplingCellServiceImpl;
      42             : } // namespace services
      43             : } // namespace coupling
      44             : 
      45             : /** generic interface class for functionality of data exchange in hybrid
      46             :  * Micro-Macro simulations.
      47             :  *  @author Philipp Neumann
      48             :  */
      49             : template <unsigned int dim> class coupling::services::CouplingCellService {
      50             : public:
      51           4 :   CouplingCellService(unsigned int ID, unsigned int topologyOffset) : _id(ID), _topologyOffset(topologyOffset) {
      52             : #if (COUPLING_MD_DEBUG == COUPLING_MD_YES)
      53             :     std::cout << "CouplingCellService::CouplingCellService(): Set ID=" << _id << std::endl;
      54             : #endif
      55             :   }
      56           0 :   virtual ~CouplingCellService() {}
      57             : 
      58             :   virtual double applyFilterPipeline() = 0;
      59             :   virtual void sendFromMacro2MDPreProcess() = 0;
      60             :   virtual void sendFromMacro2MDPostProcess() = 0;
      61             :   virtual void sendFromMacro2MD(const coupling::datastructures::FlexibleCellContainer<dim>& macro2MDBuffer) = 0;
      62             :   virtual void sendFromMD2MacroPreProcess() = 0;
      63             :   virtual void sendFromMD2MacroPostProcess() = 0;
      64             :   virtual double sendFromMD2Macro(const coupling::datastructures::FlexibleCellContainer<dim>& couplingCellContainerFromMacroscopicSolver) = 0;
      65             :   virtual void processInnerCouplingCellAfterMDTimestep() = 0;
      66             :   virtual void computeAndStoreTemperature(double temperature) = 0;
      67             :   virtual void applyTemperatureToMolecules(unsigned int t) = 0;
      68             :   virtual void distributeMass(unsigned int t) = 0;
      69             :   virtual void distributeMomentum(unsigned int t) = 0;
      70             :   virtual void applyBoundaryForce(unsigned int t) = 0;
      71             :   virtual void perturbateVelocity() = 0;
      72             :   virtual void plotEveryMicroscopicTimestep(unsigned int t) = 0;
      73             :   virtual void plotEveryMacroscopicTimestep(unsigned int t) = 0;
      74             : 
      75           0 :   virtual void initFiltering() {
      76           0 :     throw std::runtime_error("CouplingCellService: Error: Called "
      77             :                              "initFiltering for non-Impl object.");
      78             :   } /*Note: This is not pure virtual, because some implementations of this
      79             :        interface don't have a FilterPipeline. */
      80           0 :   virtual const coupling::filtering::FilterPipeline<I02, dim>* getFilterPipeline() const {
      81           0 :     throw std::runtime_error("CouplingCellService: Error: Called getFilterPipeline() in instance "
      82             :                              "without FilterPipeline.");
      83             :   } /*Note: This is not pure virtual, because some implementations of this
      84             :        interface don't have a FilterPipeline. */
      85             : 
      86           0 :   unsigned int getID() const { return _id; }
      87             : 
      88             : protected:
      89             :   const unsigned int _id; /** (unique) identifier of this coupling cell service */
      90             :   unsigned int _topologyOffset;
      91             : };
      92             : 
      93             : /** This class put together all ingredients for coupling MD and some macroscopic
      94             :  * solver. It thus triggers send/recv-operations between the coupling tool and
      95             :  * MD as well as between the coupling tool and the macroscopic solver.
      96             :  *  @author Philipp Neumann
      97             :  */
      98             : template <class LinkedCell, unsigned int dim> class coupling::services::CouplingCellServiceImpl : public coupling::services::CouplingCellService<dim> {
      99             : public:
     100             :   /** constructor. Arguments:
     101             :    *  mdSolverInterface                 - pointer to the MD solver interface
     102             :    *  macroscopicSolverInterface        - pointer to the macroscopic solver
     103             :    * interface numberProcesses                   - number of processes assuming
     104             :    * a block-like domain decomposition rank                              - rank
     105             :    * of the current process particleInsertionConfiguration    - configuration
     106             :    * object for (USHER-based) particle insertion and particle removal
     107             :    *  momentumInsertionConfiguration    - configuration object which determines
     108             :    * the momentum transfer on MD side transferStrategyConfiguration     -
     109             :    * configuration object which determines the respective transfer strategy
     110             :    *  parallelTopologyConfiguration     - configuratio object which defines the
     111             :    * parallel topology of the simulation (domain decomposition of the MD
     112             :    * simulation) numberMDTimestepsPerCouplingCycle - number of MD time steps per
     113             :    * coupling cycle couplingCellConfiguration      - configuration object
     114             :    * which determines the properties of the coupling cells topologyOffset -
     115             :    * offset in linearized topology of ranks topologyGlobalNumberProcesses     -
     116             :    * global number of processes available in overall topology
     117             :    *
     118             :    *  Note: the interface pointers are used by the CouplingCellServiceImpl;
     119             :    * they are not deleted at the end of the simulation since other (external)
     120             :    * routines may use those as well.
     121             :    */
     122             :   CouplingCellServiceImpl(
     123             :       unsigned int ID, coupling::interface::MDSolverInterface<LinkedCell, dim>* mdSolverInterface,       // interface to MD simulation
     124             :       coupling::interface::MacroscopicSolverInterface<dim>* macroscopicSolverInterface,                  // interface to macroscopic solver
     125             :       tarch::la::Vector<dim, unsigned int> numberProcesses,                                              // number of processes in all directions
     126             :       unsigned int rank,                                                                                 // current rank
     127             :       const coupling::configurations::ParticleInsertionConfiguration& particleInsertionConfiguration,    // configuration for particle
     128             :                                                                                                          // insertion
     129             :       const coupling::configurations::MomentumInsertionConfiguration& momentumInsertionConfiguration,    // configuration for momentum
     130             :                                                                                                          // insertion
     131             :       const coupling::configurations::BoundaryForceConfiguration<dim>& boundaryForceConfiguration,       // configuration for boundary forces
     132             :       const coupling::configurations::TransferStrategyConfiguration<dim>& transferStrategyConfiguration, // configuration for transfer strategy
     133             :       const coupling::configurations::ParallelTopologyConfiguration& parallelTopologyConfiguration,      // configuration for parallel topology
     134             :       const coupling::configurations::ThermostatConfiguration& thermostatConfiguration,
     135             :       unsigned int numberMDTimestepsPerCouplingCycle,                                            // number MD timesteps per coupling
     136             :                                                                                                  // cycle (required to initialise
     137             :                                                                                                  // transfer strategy)
     138             :       const coupling::configurations::CouplingCellConfiguration<dim>& couplingCellConfiguration, // configuration for coupling cells
     139             :                                                                                                  // and respective plotting
     140             :       const char* filterPipelineConfiguration, const tarch::utils::MultiMDService<dim>& multiMDService, unsigned int topologyOffset, int tws = 0);
     141             : 
     142             :   CouplingCellServiceImpl(
     143             :       unsigned int ID, coupling::interface::MDSolverInterface<LinkedCell, dim>* mdSolverInterface,       // interface to MD simulation
     144             :       coupling::interface::MacroscopicSolverInterface<dim>* macroscopicSolverInterface,                  // interface to macroscopic solver
     145             :       tarch::la::Vector<dim, unsigned int> numberProcesses,                                              // number of processes in all directions
     146             :       unsigned int rank,                                                                                 // current rank
     147             :       const coupling::configurations::ParticleInsertionConfiguration& particleInsertionConfiguration,    // configuration for particle
     148             :                                                                                                          // insertion
     149             :       const coupling::configurations::MomentumInsertionConfiguration& momentumInsertionConfiguration,    // configuration for momentum
     150             :                                                                                                          // insertion
     151             :       const coupling::configurations::BoundaryForceConfiguration<dim>& boundaryForceConfiguration,       // configuration for boundary forces
     152             :       const coupling::configurations::TransferStrategyConfiguration<dim>& transferStrategyConfiguration, // configuration for transfer strategy
     153             :       const coupling::configurations::ParallelTopologyConfiguration& parallelTopologyConfiguration,      // configuration for parallel topology
     154             :       const coupling::configurations::ThermostatConfiguration& thermostatConfiguration,
     155             :       unsigned int numberMDTimestepsPerCouplingCycle,                                            // number MD timesteps per coupling
     156             :                                                                                                  // cycle (required to initialise
     157             :                                                                                                  // transfer strategy)
     158             :       const coupling::configurations::CouplingCellConfiguration<dim>& couplingCellConfiguration, // configuration for coupling cells
     159             :                                                                                                  // and respective plotting
     160             :       const char* filterPipelineConfiguration, const tarch::utils::MultiMDService<dim>& multiMDService)
     161             :       : CouplingCellServiceImpl<LinkedCell, dim>(ID, mdSolverInterface, macroscopicSolverInterface, numberProcesses, rank, particleInsertionConfiguration,
     162             :                                                  momentumInsertionConfiguration, boundaryForceConfiguration, transferStrategyConfiguration,
     163             :                                                  parallelTopologyConfiguration, thermostatConfiguration, numberMDTimestepsPerCouplingCycle,
     164             :                                                  couplingCellConfiguration, filterPipelineConfiguration, multiMDService, 0) {}
     165             : 
     166             :   /** destructor. Frees dynamically allocated memory for particle insertion,
     167             :    * momentum insertion and the transfer strategy.
     168             :    */
     169             :   virtual ~CouplingCellServiceImpl();
     170             : 
     171             :   /** sends information from macroscopic solver to MD. The cell information from
     172             :    * the macroscopic solver is handed over as a flexible cell container
     173             :    * The coupling tool internally triggers send/recv-operations
     174             :    * (this also comprises the distributed memory parallelisation via MPI)
     175             :    * and writes the respective information to the coupling cells of the tool
     176             :    */
     177             :   void sendFromMacro2MD(const coupling::datastructures::FlexibleCellContainer<dim>& macro2MDBuffer) override;
     178             : 
     179             :   /** sends information from MD to the macroscopic solver. After the
     180             :    * send/recv-operations (this also comprises the distributed memory
     181             :    * parallelisation scenario), the information from the coupling tool is
     182             :    * written to the buffer couplingCellsFromMacroscopicSolver together with
     183             :    * the respective global cell indices
     184             :    *  (-> indices).
     185             :    *
     186             :    * @returns The runtime of filtering related code in usec.
     187             :    */
     188             :   double sendFromMD2Macro(const coupling::datastructures::FlexibleCellContainer<dim>& macroscopicSolverCellContainer) override;
     189             : 
     190             :   /** applies the filter pipeline and returns the runtime of this operation */
     191             :   double applyFilterPipeline() override;
     192             : 
     193             :   void sendFromMacro2MDPreProcess() override;
     194             : 
     195             :   void sendFromMacro2MDPostProcess() override;
     196             : 
     197             :   void sendFromMD2MacroPreProcess() override;
     198             : 
     199           0 :   void sendFromMD2MacroPostProcess() override {}
     200             : 
     201             :   /** carries out coupling-dependent operations (such as sampling) on the
     202             :    * non-ghost coupling cells after each MD time step. This method needs thus
     203             :    * to be called from the MD simulation.
     204             :    */
     205             :   void processInnerCouplingCellAfterMDTimestep() override;
     206             : 
     207             :   /** sets the temperature value in all coupling cells. If the value of
     208             :    * temperature is -1.0, we set the local temperature of each coupling cell
     209             :    * (and just store this value in the coupling cell). Otherwise, we apply
     210             :    * the given temperature in all cells. In the latter case, this also resembles
     211             :    * a first thermostat-like operation.
     212             :    */
     213             :   void computeAndStoreTemperature(double temperature) override;
     214             : 
     215             :   /** applies a thermostat in all non-ghost coupling cells. */
     216             :   void applyTemperatureToMolecules(unsigned int t) override;
     217             : 
     218             :   /** applies a boundary force to molecules which are close to an open boundary.
     219             :    */
     220             :   void applyBoundaryForce(unsigned int t) override;
     221             : 
     222             :   /** distributes mass in the system. */
     223             :   void distributeMass(unsigned int t) override;
     224             : 
     225             :   /** distributes momentum in MD. Should typically be called after force
     226             :    * accumulation since momentum distribution may depend on current forces. */
     227             :   void distributeMomentum(unsigned int t) override;
     228             : 
     229             :   /** applies a new velocity to each particle according to its cell's mean
     230             :    * velocity. */
     231             :   void perturbateVelocity() override;
     232             : 
     233             :   /** plots coupling cell and molecule information at some time step t. The
     234             :    * correct triggering of plotting needs to be established from the main
     235             :    * coupling loop which is outside the coupling tool (not included in this
     236             :    * function).
     237             :    */
     238             :   void plotEveryMicroscopicTimestep(unsigned int t) override;
     239             :   void plotEveryMacroscopicTimestep(unsigned int t) override;
     240             : 
     241             :   /**
     242             :    * Initialises the _filterPipeline member. Called from _multiMDCellService's
     243             :    * constructFilterPipelines(). Make sure to delete _filterPipeline in
     244             :    * ~CouplingCellServiceImpl()
     245             :    */
     246           0 :   void initFiltering() override {
     247           0 :     _filterPipeline = new coupling::filtering::FilterPipeline<I02, dim>(_couplingCells, coupling::filtering::Scope::perInstance, _multiMDService,
     248             :                                                                         _filterPipelineConfiguration);
     249           0 :   }
     250             : 
     251           0 :   const coupling::filtering::FilterPipeline<I02, dim>* getFilterPipeline() const override { return _filterPipeline; }
     252             : 
     253             :   /**
     254             :    * Creates a new filter from scratch and appends it to a sequence that is part
     255             :    * of this service's filter pipelining system. For that, the desired
     256             :    * sequence's identifier and two functions are needed:
     257             :    *  - applyScalar What to do with scalar properties of the sequence's
     258             :    * Coupling Cells.
     259             :    *  - applyVector: What to do with properties stored as vectors of the
     260             :    * sequence's of Coupling Cells.
     261             :    */
     262             :   /*
     263             :    * TODO: MOVE COMMENT
     264             :   void addFilterToSequence(     const char *sequenceIdentifier,
     265             :                                                           const
     266             :   std::function<std::vector<double> (std::vector<double> cells_s,
     267             :   std::vector<std::array<unsigned int, dim>> indices)>* applyScalar, const
     268             :   std::function<std::vector<std::array<double, dim>>
     269             :   (std::vector<std::array<double, dim>> cells_v, std::vector<std::array<unsigned
     270             :   int, dim>> indices)>* applyVector, int filterIndex = -1
     271             :   );*/
     272             : 
     273             :   /** returns the coupling cells. This functions is meant to be used in test
     274             :    * scenarios and for debugging only! DO NOT USE IT FOR OTHER PURPOSES! */
     275             :   coupling::datastructures::LinkedCellContainer<LinkedCell, dim>& getCouplingCells() { return _couplingCells; }
     276             : 
     277             : private:
     278             : // ------------------- INCLUDE WRAPPER DEFINITIONS
     279             : // -------------------------------------
     280             : #include "CouplingCellTraversalWrappers.cpph"
     281             : 
     282             :   /** initialises the index structures for USHER scheme */
     283             :   void initIndexVectors4Usher();
     284             : 
     285             :   tarch::la::Vector<dim, double> getPositionOfFirstLocalGhostCell() const;
     286             : 
     287           4 :   std::function<void(Wrapper&)> initCorrectApplicationOfThermostat(const coupling::configurations::ThermostatConfiguration& thermostatConfiguration) {
     288           4 :     if (thermostatConfiguration.getThermostatRegionType() == coupling::configurations::ThermostatConfiguration::ThermostatRegion::all)
     289           0 :       return [this](Wrapper& wrapper) { _couplingCells.applyToLocalNonGhostCouplingCellsWithLinkedCells(wrapper); };
     290           4 :     else if (thermostatConfiguration.getThermostatRegionType() == coupling::configurations::ThermostatConfiguration::ThermostatRegion::outerLayers)
     291           0 :       return [this, &thermostatConfiguration](Wrapper& wrapper) {
     292           0 :         _couplingCells.applyXLayersOfGlobalNonGhostCellsWithLinkedCells(wrapper, thermostatConfiguration.getCells2Use());
     293           0 :       };
     294           4 :     else if (thermostatConfiguration.getThermostatRegionType() == coupling::configurations::ThermostatConfiguration::ThermostatRegion::onlyOutestLayer)
     295           0 :       return [this](Wrapper& wrapper) { _couplingCells.applyToFirstLayerOfGlobalNonGhostCellsWithLinkedCells(wrapper); };
     296             :     else
     297           4 :       return [](Wrapper& wrapper) {};
     298             :   }
     299             : 
     300             :   /** number of MD time steps in each coupling cycle */
     301             :   const unsigned int _numberMDTimestepsPerCouplingCycle;
     302             : 
     303             :   /** interface for MD solver */
     304             :   coupling::interface::MDSolverInterface<LinkedCell, dim>* _mdSolverInterface;
     305             : 
     306             :   /** interface for macroscopic solver */
     307             :   coupling::interface::MacroscopicSolverInterface<dim>* _macroscopicSolverInterface;
     308             : 
     309             :   /** for quantity transfer between solvers */
     310             :   coupling::sendrecv::FromMacro2MD<coupling::datastructures::CouplingCell<dim>, dim> _fromMacro2MD;
     311             :   coupling::sendrecv::DataExchangeFromMacro2MD<dim> _deFromMacro2MD;
     312             :   coupling::sendrecv::FromMD2Macro<coupling::datastructures::CouplingCell<dim>, dim> _fromMD2Macro;
     313             :   coupling::sendrecv::DataExchangeFromMD2Macro<dim> _deFromMD2Macro;
     314             : 
     315             :   /** storage for coupling cells in coupling tool */
     316             :   coupling::datastructures::LinkedCellContainer<LinkedCell, dim> _couplingCells;
     317             : 
     318             :   /** filter pipeline, used to apply filters in sendFromMD2Macro */
     319             :   coupling::filtering::FilterPipeline<I02, dim>* _filterPipeline;
     320             : 
     321             :   /**parameters needed in initFiltering() */
     322             :   const char* _filterPipelineConfiguration;
     323             :   const tarch::utils::MultiMDService<dim> _multiMDService;
     324             : 
     325             :   /** needed for insertion of momentum */
     326             :   coupling::MomentumInsertion<LinkedCell, dim>* _momentumInsertion;
     327             :   coupling::configurations::MomentumInsertionConfiguration::MomentumInsertionType _momentumInsertionType;
     328             :   /** needed for insertion of particles, e.g. USHER */
     329             :   coupling::ParticleInsertion<LinkedCell, dim>* _particleInsertion;
     330             :   const tarch::la::Vector<dim, unsigned int> _numberLinkedCellsPerCouplingCell;
     331             :   const coupling::configurations::ParticleInsertionConfiguration::ParticleInsertionType _particleInsertionType;
     332             :   /** coupling strategy */
     333             :   coupling::transferstrategies::TransferStrategy<LinkedCell, dim>* _transferStrategy;
     334             : 
     335             :   /** controls the kinetic energy of the system, i.e. maintains temperature in
     336             :    * case of changing mass/momentum. */
     337             :   coupling::KineticEnergyController<LinkedCell, dim> _kineticEnergyController;
     338             :   /** controls and apply boundary forces to molecules close to open
     339             :    * boundaries.*/
     340             :   coupling::BoundaryForceController<LinkedCell, dim>* _boundaryForceController;
     341             :   /** controls/ maintains momentum, e.g. after particle insertion */
     342             :   coupling::MomentumController<LinkedCell, dim> _momentumController;
     343             : 
     344             :   std::function<void(Wrapper&)> _applyAccordingToConfiguration;
     345             : 
     346             :   /** information for plotting */
     347             :   const std::string _microscopicFilename;
     348             :   const unsigned int _writeEveryMicroscopicTimestep;
     349             :   const std::string _macroscopicFilename;
     350             :   const unsigned int _writeEveryMacroscopicTimestep;
     351             : 
     352             :   /** index vectors for block-usher scheme
     353             :    * -----------------------------------------------------*/
     354             :   // start and end coordinate for block loop over coupling cells (with 3
     355             :   // entries always!)
     356             :   tarch::la::Vector<3, unsigned int> _usherCellStart[1 << dim];
     357             :   tarch::la::Vector<3, unsigned int> _usherCellEnd[1 << dim];
     358             :   tarch::la::Vector<dim, unsigned int> _usherRange[1 << dim];
     359             :   // offset in red-black loops nested within the block loops (always 0 or 1
     360             :   // entries)
     361             :   tarch::la::Vector<3, unsigned int> _usherCellOffset[1 << dim];
     362             : };
     363             : #include "CouplingCellService.cpph"
     364             : 
     365             : #endif // _MOLECULARDYNAMICS_COUPLING_SERVICES_COUPLINGCELLSERVICE_H_

Generated by: LCOV version 1.14