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_
|