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