Line data Source code
1 : #pragma once
2 :
3 : // parallel topologies
4 : #include "coupling/CouplingMDDefinitions.h"
5 : #include "coupling/paralleltopology/ParallelTopology.h"
6 : #include "coupling/paralleltopology/ParallelTopologyFactory.h"
7 :
8 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
9 : #include <mpi.h>
10 : #endif
11 :
12 : namespace coupling {
13 : namespace indexing {
14 :
15 : template <unsigned int dim> class IndexingService;
16 :
17 : }
18 : } // namespace coupling
19 :
20 : // Include CellIndex template class definition
21 : #include "coupling/indexing/IndexTypes.h"
22 :
23 : namespace coupling {
24 : namespace indexing {
25 :
26 : template <unsigned int dim> std::vector<unsigned int> getRanksForGlobalIndex(const BaseIndex<dim>& globalCellIndex, unsigned int topologyOffset);
27 :
28 : } // namespace indexing
29 : } // namespace coupling
30 :
31 : // Include non-member functions operating on indexes
32 : #include "Operations.h"
33 :
34 : class IndexingServiceTest;
35 :
36 : /**
37 : * Singleton service class initialising lower and upper boundaries of all
38 : * possible CellIndex specialisations.
39 : *
40 : * @tparam dim number of dimensions of the coupled simulation
41 : * @param simpleMDConfig config object of SimpleMD instance used in coupling
42 : * @param mamicoConfig config object containg general information of coupling
43 : * process
44 : * @param outer region
45 : *
46 : * @author Felix Maurer
47 : */
48 184 : template <unsigned int dim> class coupling::indexing::IndexingService {
49 : public:
50 14295443 : static IndexingService& getInstance() {
51 14295627 : static IndexingService singleton{};
52 14295443 : return singleton;
53 : }
54 :
55 748 : void initWithCells(tarch::la::Vector<dim, unsigned int> globalNumberCouplingCells, tarch::la::Vector<dim, unsigned int> numberProcesses,
56 : coupling::paralleltopology::ParallelTopologyType parallelTopologyType, unsigned int outerRegion, const unsigned int rank
57 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
58 : ,
59 : MPI_Comm comm = MPI_COMM_WORLD
60 : #endif
61 : ) {
62 : // regular grid
63 2992 : tarch::la::Vector<dim, std::vector<unsigned int>> subdomainWeights;
64 2992 : for (unsigned int i = 0; i < dim; i++) {
65 2244 : subdomainWeights[i].reserve(numberProcesses[i]);
66 6156 : for (unsigned int j = 0; j < numberProcesses[i]; j++) {
67 3912 : subdomainWeights[i].push_back(1);
68 : }
69 : }
70 1496 : initWithCells(subdomainWeights, globalNumberCouplingCells, numberProcesses, parallelTopologyType, outerRegion, rank
71 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
72 : ,
73 : comm
74 : #endif
75 : );
76 744 : }
77 :
78 : void initWithCells(const tarch::la::Vector<dim, std::vector<unsigned int>>& subdomainWeights, tarch::la::Vector<dim, unsigned int> globalNumberCouplingCells,
79 : tarch::la::Vector<dim, unsigned int> numberProcesses, coupling::paralleltopology::ParallelTopologyType parallelTopologyType,
80 : unsigned int outerRegion, const unsigned int rank
81 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
82 : ,
83 : MPI_Comm comm = MPI_COMM_WORLD
84 : #endif
85 : );
86 :
87 0 : void initWithMDSize(const tarch::la::Vector<3, double>& globalMDDomainSize, const tarch::la::Vector<3, double>& globalMDDomainOffset,
88 : const tarch::la::Vector<3, unsigned int>& mdNumberProcesses, const tarch::la::Vector<3, double>& couplingCellSize,
89 : coupling::paralleltopology::ParallelTopologyType parallelTopologyType, unsigned int outerRegion, unsigned int rank
90 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
91 : ,
92 : MPI_Comm comm = MPI_COMM_WORLD
93 : #endif
94 : ) {
95 : // regular grid
96 0 : tarch::la::Vector<dim, std::vector<unsigned int>> subdomainWeights;
97 0 : for (unsigned int i = 0; i < dim; i++) {
98 0 : subdomainWeights[i].reserve(mdNumberProcesses[i]);
99 0 : for (unsigned int j = 0; j < mdNumberProcesses[i]; j++) {
100 0 : subdomainWeights[i].push_back(1);
101 : }
102 : }
103 :
104 0 : initWithMDSize(subdomainWeights, globalMDDomainSize, globalMDDomainOffset, mdNumberProcesses, couplingCellSize, parallelTopologyType, outerRegion, rank
105 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
106 : ,
107 : comm
108 : #endif
109 : );
110 0 : }
111 0 : void initWithMDSize(const tarch::la::Vector<dim, std::vector<unsigned int>>& subdomainWeights, const tarch::la::Vector<3, double>& globalMDDomainSize,
112 : const tarch::la::Vector<3, double>& globalMDDomainOffset, const tarch::la::Vector<3, unsigned int>& mdNumberProcesses,
113 : const tarch::la::Vector<3, double>& couplingCellSize, coupling::paralleltopology::ParallelTopologyType parallelTopologyType,
114 : unsigned int outerRegion, unsigned int rank
115 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
116 : ,
117 : MPI_Comm comm = MPI_COMM_WORLD
118 : #endif
119 : ) {
120 0 : _globalMDDomainSize = globalMDDomainSize;
121 0 : _globalMDDomainOffset = globalMDDomainOffset;
122 0 : _couplingCellSize = couplingCellSize;
123 0 : _initedWithMDSize = true;
124 :
125 : // calculate total number of coupling cells on all ranks in Base Domain
126 0 : tarch::la::Vector<dim, unsigned int> globalNumberCouplingCells(0);
127 0 : for (unsigned int d = 0; d < dim; d++) {
128 0 : globalNumberCouplingCells[d] = (unsigned int)floor(globalMDDomainSize[d] / couplingCellSize[d] + 0.5);
129 :
130 0 : if (fabs((globalNumberCouplingCells[d]) * couplingCellSize[d] - globalMDDomainSize[d]) > 1e-13)
131 0 : std::cout << "IndexingService: Deviation of domain size > 1e-13!" << std::endl;
132 : }
133 :
134 0 : initWithCells(subdomainWeights, globalNumberCouplingCells, mdNumberProcesses, parallelTopologyType, outerRegion, rank
135 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES)
136 : ,
137 : comm
138 : #endif
139 : );
140 0 : }
141 :
142 732 : void finalize() {
143 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
144 732 : _isInitialized = false;
145 : #endif
146 0 : }
147 :
148 : /**
149 : * Determines all ranks that contain a certain global BaseIndex.
150 : * Ripped from deprecated IndexConversion.
151 : *
152 : * @param globalCellIndex index to be looked up
153 : * @param globalNumberCouplingCells global number of cells in BaseIndex
154 : * domain EXCLUDING global ghost layer cells.
155 : * @returns vector of all cells which contain the index
156 : */
157 : std::vector<unsigned int> getRanksForGlobalIndex(const BaseIndex<dim>& globalCellIndex, unsigned int topologyOffset) const;
158 :
159 : unsigned int getUniqueRankForCouplingCell(const BaseIndex<dim>& globalCellIndex, unsigned int topologyOffset) const;
160 :
161 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES) // parallel scenario
162 1535 : MPI_Comm getComm() const {
163 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
164 1535 : if (!_isInitialized) {
165 8 : throw std::runtime_error(std::string("IndexingService: Called index system getComm() before initialization! "));
166 : }
167 : #endif
168 :
169 1531 : return _comm;
170 : }
171 : #endif
172 :
173 188 : unsigned int getRank() const {
174 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
175 188 : if (!_isInitialized) {
176 8 : throw std::runtime_error(std::string("IndexingService: Called index system getRank() before initialization! "));
177 : }
178 : #endif
179 :
180 184 : return _rank;
181 : }
182 :
183 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
184 14292236 : bool isInitialized() const { return _isInitialized; }
185 : #endif
186 :
187 : /** returns the global domain size of the MD domain (excl. ghost layer which
188 : * naturally is not part of MD).
189 : * @returns the total size of the md simulation domain (dimensional) */
190 0 : tarch::la::Vector<dim, double> getGlobalMDDomainSize() const {
191 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
192 0 : if (!_isInitialized) {
193 0 : throw std::runtime_error(std::string("IndexingService: Called getGlobalMDDomainSize() before initalization! "));
194 : }
195 0 : if (!_initedWithMDSize) {
196 0 : throw std::runtime_error(std::string("IndexingService: Called getGlobalMDDomainSize() without calling initWithMDSize()! "));
197 : }
198 : #endif
199 0 : return _globalMDDomainSize;
200 : }
201 :
202 : /** @brief returns the offset, i.e. the lower,left... corner coordinate, of
203 : * the MD domain.
204 : * @returns the offset of the MD domain */
205 0 : tarch::la::Vector<dim, double> getGlobalMDDomainOffset() const {
206 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
207 0 : if (!_isInitialized) {
208 0 : throw std::runtime_error(std::string("IndexingService: Called getGlobalMDDomainOffset() before initalization! "));
209 : }
210 0 : if (!_initedWithMDSize) {
211 0 : throw std::runtime_error(std::string("IndexingService: Called getGlobalMDDomainOffset() without calling initWithMDSize()! "));
212 : }
213 : #endif
214 0 : return _globalMDDomainOffset;
215 : }
216 :
217 : /** @brief returns the vector size of each coupling cell.
218 : * @returns the size of the coupling cells (dimensional) */
219 0 : tarch::la::Vector<dim, double> getCouplingCellSize() const {
220 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
221 0 : if (!_isInitialized) {
222 0 : throw std::runtime_error(std::string("IndexingService: Called getCouplingCellSize() before initalization! "));
223 : }
224 0 : if (!_initedWithMDSize) {
225 0 : throw std::runtime_error(std::string("IndexingService: Called getCouplingCellSize() without calling initWithMDSize()! "));
226 : }
227 : #endif
228 0 : return _couplingCellSize;
229 : }
230 :
231 0 : unsigned int getScalarNumberProcesses() const {
232 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
233 0 : if (!_isInitialized) {
234 0 : throw std::runtime_error(std::string("IndexingService: Called getScalarNumberProcesses() before initalization! "));
235 : }
236 : #endif
237 0 : return _scalarNumberProcesses;
238 : }
239 :
240 0 : BaseIndex<dim> getCellIndex(tarch::la::Vector<dim, double> position) const {
241 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
242 0 : if (!_isInitialized) {
243 0 : throw std::runtime_error(std::string("IndexingService: Called getCellIndex() before initalization! "));
244 : }
245 0 : if (!_initedWithMDSize) {
246 0 : throw std::runtime_error(std::string("IndexingService: Called getCellIndex() without calling initWithMDSize()! "));
247 : }
248 : #endif
249 :
250 0 : tarch::la::Vector<dim, int> res_raw;
251 0 : for (unsigned int d = 0; d < dim; d++) {
252 0 : const double buf = position[d] - (_globalMDDomainOffset[d] - _couplingCellSize[d]);
253 0 : res_raw[d] = buf / _couplingCellSize[d];
254 : }
255 :
256 0 : BaseIndex<dim> res{res_raw};
257 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
258 0 : if (!BaseIndex<dim>::contains(res)) {
259 0 : throw std::runtime_error(std::string("IndexingService::getCellIndex(): Invalid conversion!"));
260 : }
261 : #endif
262 0 : return res;
263 : }
264 :
265 : private:
266 : unsigned int getUniqueRankForCouplingCell(tarch::la::Vector<dim, unsigned int> globalCellIndex,
267 : const tarch::la::Vector<dim, unsigned int>& globalNumberCouplingCells, unsigned int topologyOffset) const;
268 :
269 : /*const*/ tarch::la::Vector<dim, unsigned int> _numberProcesses; // TODO: make const
270 : unsigned int _scalarNumberProcesses;
271 : const coupling::paralleltopology::ParallelTopology<dim>* _parallelTopology;
272 : #if (COUPLING_MD_PARALLEL == COUPLING_MD_YES) // parallel scenario
273 : MPI_Comm _comm;
274 : #endif
275 : unsigned int _rank;
276 : #if (COUPLING_MD_ERROR == COUPLING_MD_YES)
277 : bool _isInitialized = false;
278 : #endif
279 : bool _initedWithMDSize = false;
280 : tarch::la::Vector<dim, std::vector<unsigned int>> _subdomainOwnership;
281 : tarch::la::Vector<dim, double> _globalMDDomainSize;
282 : tarch::la::Vector<dim, double> _globalMDDomainOffset;
283 : tarch::la::Vector<dim, double> _couplingCellSize;
284 : coupling::paralleltopology::ParallelTopologyType _parallelTopologyType;
285 : friend IndexingServiceTest;
286 : };
|