LCOV - code coverage report
Current view: top level - coupling/services - CouplingCellService.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 27.3 % 22 6
Test Date: 2026-08-21 15:14:06 Functions: 16.7 % 6 1

            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/DataExchangeFromAllMacro2MD.h"
      29              : #include "coupling/sendrecv/DataExchangeFromMD2Macro.h"
      30              : #include "coupling/sendrecv/DataExchangeFromMacro2MD.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<dim>& 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<dim>& 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<3>::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 2.0-1