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

Generated by: LCOV version 1.14