ALL 0.9.4
A Loadbalacing Library
Loading...
Searching...
No Matches
ALL_Staggered.hpp
Go to the documentation of this file.
1/*
2Copyright 2018-2026 Rene Halver, Forschungszentrum Juelich GmbH, Germany
3Copyright 2018-2026 Godehard Sutmann, Forschungszentrum Juelich GmbH, Germany
4Copyright 2026-2026 Jonas Kroschewski, Forschungszentrum Juelich GmbH, Germany
5
6
7Redistribution and use in source and binary forms, with or without modification,
8are permitted provided that the following conditions are met:
9
101. Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
12
132. Redistributions in binary form must reproduce the above copyright notice,
14this list of conditions and the following disclaimer in the documentation and/or
15 other materials provided with the distribution.
16
173. Neither the name of the copyright holder nor the names of its contributors
18may be used to endorse or promote products derived from this software without
19 specific prior written permission.
20
21THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
25ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*/
32
33#ifndef ALL_STAGGERED_HEADER_INCLUDED
34#define ALL_STAGGERED_HEADER_INCLUDED
35
37#include "ALL_LB.hpp"
38#include "ALL_Defines.h"
39#include <exception>
40#include <mpi.h>
41#include <vector>
42
43namespace ALL {
44
54template <class T, class W> class Staggered_LB : public LB<T, W> {
55public:
62 Staggered_LB(int d, W w, T g) : LB<T, W>(d, g) {
63 this->setWork(w);
64
65 // array of MPI communicators for each direction (to collect work
66 // on each plane)
67 communicators.resize(d);
68 for (int _d = 0; _d < d; ++_d)
69 communicators.at(_d) = MPI_COMM_NULL;
70
71 nNeighbors.resize(2 * d);
72 //by default automatic calculation of gamma is turned on
73 this->gammaAutoCalc = true;
74 }
75
78 ;
79
81 void setup() override;
82
87 void balance(int step) override;
88
92 virtual std::vector<int> &getNeighbors() override;
93
96 virtual void setAdditionalData(known_unused const void *data) override {}
97
101 virtual W getEstimatedEfficiency() override {return (W)-1;};
102
103private:
105 MPI_Datatype MPIDataTypeT;
107 MPI_Datatype MPIDataTypeW;
108
110 std::vector<MPI_Comm> communicators;
111
113 std::vector<int> neighbors;
115 std::vector<int> nNeighbors;
116
118 void find_neighbors();
119};
120
121template <class T, class W> Staggered_LB<T, W>::~Staggered_LB() {
122 int dimension = this->getDimension();
123 for (int i = 1; i < dimension; ++i) {
124 if (communicators.at(i) != MPI_COMM_NULL)
125 MPI_Comm_free(&communicators.at(i));
126 }
127}
128
129// setup routine for the tensor-based load-balancing scheme
130// requires:
131// this->globalComm (int): cartesian MPI communicator, from
132// which separate sub communicators
133// are derived in order to represent
134// each plane of domains in the system
135template <class T, class W> void Staggered_LB<T, W>::setup() {
136 int status;
137 int dimension = this->getDimension();
138
139 // check if Communicator is cartesian
140 MPI_Topo_test(this->globalComm, &status);
141 if (status != MPI_CART) {
143 __FILE__, __func__, __LINE__,
144 "Cartesian MPI communicator required, passed communicator is not "
145 "cartesian");
146 }
147
148 // get the local coordinates, periodicity and global size from the MPI
149 // communicator
150 MPI_Cart_get(this->globalComm, dimension, this->global_dims.data(),
151 this->periodicity.data(), this->local_coords.data());
152
153 // get the local rank from the MPI communicator
154 MPI_Cart_rank(this->globalComm, this->local_coords.data(), &this->localRank);
155
156 // create sub-communicators
157
158 if (communicators.at(1) != MPI_COMM_NULL)
159 MPI_Comm_free(&communicators.at(1));
160 if (communicators.at(2) != MPI_COMM_NULL)
161 MPI_Comm_free(&communicators.at(2));
162
163 // z-plane
164 MPI_Comm_split(this->globalComm, this->local_coords.at(2),
165 this->local_coords.at(0) +
166 this->local_coords.at(1) * this->global_dims.at(0),
167 &communicators.at(2));
168
169 // y-column
170 MPI_Comm_split(this->globalComm,
171 this->local_coords.at(2) * this->global_dims.at(1) +
172 this->local_coords.at(1),
173 this->local_coords.at(0), &communicators.at(1));
174
175 // only cell itself
176 communicators.at(0) = MPI_COMM_SELF;
177
178 // determine correct MPI data type for template T
179 if (std::is_same<T, double>::value)
180 MPIDataTypeT = MPI_DOUBLE;
181 else if (std::is_same<T, float>::value)
182 MPIDataTypeT = MPI_FLOAT;
183 else if (std::is_same<T, int>::value)
184 MPIDataTypeT = MPI_INT;
185 else if (std::is_same<T, long>::value)
186 MPIDataTypeT = MPI_LONG;
187 else {
189 __FILE__, __func__, __LINE__,
190 "Invalid data type for boundaries given (T)");
191 }
192
193 // determine correct MPI data type for template W
194 if (std::is_same<W, double>::value)
195 MPIDataTypeW = MPI_DOUBLE;
196 else if (std::is_same<W, float>::value)
197 MPIDataTypeW = MPI_FLOAT;
198 else if (std::is_same<W, int>::value)
199 MPIDataTypeW = MPI_INT;
200 else if (std::is_same<W, long>::value)
201 MPIDataTypeW = MPI_LONG;
202 else {
203 throw InvalidCommTypeException(__FILE__, __func__, __LINE__,
204 "Invalid data type for work given (W)");
205 }
206
207 // calculate neighbors
208 int rank_left, rank_right;
209
210 neighbors.clear();
211 for (int i = 0; i < dimension; ++i) {
212 MPI_Cart_shift(this->globalComm, i, 1, &rank_left, &rank_right);
213 neighbors.push_back(rank_left);
214 neighbors.push_back(rank_right);
215 }
216}
217
218template <class T, class W> void Staggered_LB<T, W>::balance(int) {
219 std::vector<Point<T>> newVertices = this->vertices;
220 int dimension = this->getDimension();
221
222 // store original vertices
223 this->prevVertices = this->vertices;
224
225 // loop over all available dimensions
226 for (int i = 0; i < dimension; ++i) {
227 W work_local_plane;
228#ifdef ALL_DEBUG_ENABLED
229 MPI_Barrier(this->globalComm);
230 if (this->localRank == 0)
231 std::cout << "ALL::Staggered_LB::balance(): before work computation..."
232 << std::endl;
233#endif
234 // collect work from all processes in the same plane
235 MPI_Allreduce(this->work.data(), &work_local_plane, 1, MPIDataTypeW,
236 MPI_SUM, communicators[i]);
237
238#ifdef ALL_DEBUG_ENABLED
239 MPI_Barrier(this->globalComm);
240 if (this->localRank == 0)
241 std::cout << "ALL::Staggered_LB::balance(): before work distribution..."
242 << std::endl;
243#endif
244 // correct right border:
245
246 W remote_work;
247 T local_size;
248 T remote_size;
249 // determine neighbors
250 int rank_left, rank_right;
251
252 MPI_Cart_shift(this->globalComm, i, 1, &rank_left, &rank_right);
253
254 // collect work from right neighbor plane
255 MPI_Request sreq, rreq;
256 MPI_Status sstat, rstat;
257
258 MPI_Irecv(&remote_work, 1, MPIDataTypeW, rank_right, 0, this->globalComm,
259 &rreq);
260 MPI_Isend(&work_local_plane, 1, MPIDataTypeW, rank_left, 0,
261 this->globalComm, &sreq);
262 MPI_Wait(&sreq, &sstat);
263 MPI_Wait(&rreq, &rstat);
264
265 // collect size in dimension from right neighbor plane
266
267 local_size = this->prevVertices.at(1)[i] - this->prevVertices.at(0)[i];
268
269 MPI_Irecv(&remote_size, 1, MPIDataTypeT, rank_right, 0, this->globalComm,
270 &rreq);
271 MPI_Isend(&local_size, 1, MPIDataTypeT, rank_left, 0, this->globalComm,
272 &sreq);
273 MPI_Wait(&sreq, &sstat);
274 MPI_Wait(&rreq, &rstat);
275
276 // automatic selection of gamma to guarantee stability of method (choice of
277 // user gamma ignored)
278 if(this->gammaAutoCalc == true) {
279 this->gamma =
280 std::max(4.1, 2.0 * (1.0 + std::max(local_size, remote_size) /
281 std::min(local_size, remote_size)));
282 }
283
284#ifdef ALL_DEBUG_ENABLED
285 MPI_Barrier(this->globalComm);
286 if (this->localRank == 0)
287 std::cout << "ALL::Staggered_LB::balance(): before shift calculation..."
288 << std::endl;
289#endif
290
291 T shift = Functions::borderShift1d(
292 rank_right, this->local_coords.at(i), this->global_dims.at(i),
293 work_local_plane, remote_work, local_size, remote_size, this->gamma,
294 this->minSize[i]);
295
296#ifdef ALL_DEBUG_ENABLED
297 MPI_Barrier(this->globalComm);
298 if (this->localRank == 0)
299 std::cout << "ALL::Staggered_LB::balance(): before shift distibution..."
300 << std::endl;
301#endif
302 // send shift to right neighbors
303 T remote_shift = (T)0;
304
305 MPI_Irecv(&remote_shift, 1, MPIDataTypeT, rank_left, 0, this->globalComm,
306 &rreq);
307 MPI_Isend(&shift, 1, MPIDataTypeT, rank_right, 0, this->globalComm, &sreq);
308 MPI_Wait(&sreq, &sstat);
309 MPI_Wait(&rreq, &rstat);
310
311#ifdef ALL_DEBUG_ENABLED
312 MPI_Barrier(this->globalComm);
313 std::cout << this->localRank << ": shift = " << shift
314 << " remoteShift = " << remote_shift
315 << " vertices: " << this->vertices.at(0)[i] << ", "
316 << this->vertices.at(1)[i] << std::endl;
317#endif
318
319 // for now: test case for simple program
320
321 // if a left neighbor exists: shift left border
322 if (rank_left != MPI_PROC_NULL && this->local_coords[i] != 0)
323 newVertices.at(0)[i] = this->prevVertices.at(0)[i] + remote_shift;
324 else
325 newVertices.at(0)[i] = this->prevVertices.at(0)[i];
326
327 // if a right neighbor exists: shift right border
328 if (rank_right != MPI_PROC_NULL &&
329 this->local_coords[i] != this->global_dims[i] - 1)
330 newVertices.at(1)[i] = this->prevVertices.at(1)[i] + shift;
331 else
332 newVertices.at(1)[i] = this->prevVertices.at(1)[i];
333
334 // check if vertices are crossed and throw exception if something went wrong
335 if (newVertices.at(1)[i] < newVertices.at(0)[i]) {
336 std::cout << "ERROR on process: " << this->localRank << std::endl;
338 __FILE__, __func__, __LINE__,
339 "Lower border of process larger than upper border of process!");
340 }
341
342 this->setVertices(newVertices);
343
344#ifdef ALL_DEBUG_ENABLED
345 MPI_Barrier(this->globalComm);
346 if (this->localRank == 0)
347 std::cout << "ALL::Staggered_LB::balance(): before neighbor search..."
348 << std::endl;
349#endif
350 find_neighbors();
351 }
352}
353
354template <class T, class W> void Staggered_LB<T, W>::find_neighbors() {
355 auto work = this->getWork();
356 auto vertices = this->prevVertices;
357 auto shifted_vertices = this->vertices;
358
359 neighbors.clear();
360 // collect work from right neighbor plane
361 MPI_Request sreq, rreq;
362 MPI_Status sstat, rstat;
363 // array to store neighbor vertices in Y/Z direction (reused)
364 T *vertices_loc = new T[4];
365 T *vertices_rem = new T[8 * this->global_dims[0] * this->global_dims[1]];
366
367 int rem_rank;
368 int rem_coords[3];
369
370 // determine neighbors
371 int rank_left, rank_right;
372
373 // offset to get the correct rank
374 int rank_offset;
375 int offset_coords[3];
376
377 // X-neighbors are static
378 nNeighbors.at(0) = nNeighbors.at(1) = 1;
379
380 // find X-neighbors
381 MPI_Cart_shift(this->globalComm, 0, 1, &rank_left, &rank_right);
382
383 // store X-neighbors
384 neighbors.push_back(rank_left);
385 neighbors.push_back(rank_right);
386
387 // find Y-neighbors to get border information from
388 MPI_Cart_shift(this->globalComm, 1, 1, &rank_left, &rank_right);
389
390 // collect border information from local column
391 vertices_loc[0] = shifted_vertices.at(0)[0];
392 vertices_loc[1] = shifted_vertices.at(1)[0];
393 MPI_Allgather(vertices_loc, 2, MPIDataTypeT,
394 vertices_rem + 2 * this->global_dims[0], 2, MPIDataTypeT,
395 communicators[1]);
396
397 // exchange local column information with upper neighbor in Y direction (cart
398 // grid)
399 MPI_Irecv(vertices_rem, 2 * this->global_dims[0], MPIDataTypeT, rank_left, 0,
400 this->globalComm, &rreq);
401 MPI_Isend(vertices_rem + 2 * this->global_dims[0], 2 * this->global_dims[0],
402 MPIDataTypeT, rank_right, 0, this->globalComm, &sreq);
403
404 // determine the offset in ranks
405 offset_coords[0] = 0;
406 offset_coords[1] = this->local_coords[1] - 1;
407 offset_coords[2] = this->local_coords[2];
408
409 rem_coords[1] = offset_coords[1];
410 rem_coords[2] = offset_coords[2];
411
412 MPI_Cart_rank(this->globalComm, offset_coords, &rank_offset);
413
414 // wait for communication
415 MPI_Wait(&sreq, &sstat);
416 MPI_Wait(&rreq, &rstat);
417
418 // iterate about neighbor borders to determine the neighborship relation
419 nNeighbors.at(2) = 0;
420 for (int x = 0; x < this->global_dims[0]; ++x) {
421 if ((vertices_rem[2 * x] <= vertices_loc[0] &&
422 vertices_loc[0] < vertices_rem[2 * x + 1]) ||
423 (vertices_rem[2 * x] < vertices_loc[1] &&
424 vertices_loc[1] <= vertices_rem[2 * x + 1]) ||
425 (vertices_rem[2 * x] >= vertices_loc[0] &&
426 vertices_loc[0] < vertices_rem[2 * x + 1] &&
427 vertices_loc[1] >= vertices_rem[2 * x + 1])) {
428 nNeighbors.at(2)++;
429 rem_coords[0] = x;
430 MPI_Cart_rank(this->globalComm, rem_coords, &rem_rank);
431 neighbors.push_back(rem_rank);
432 }
433 }
434
435 // barrier to ensure every process concluded the calculations before
436 // overwriting remote borders!
437 MPI_Barrier(this->globalComm);
438
439 // exchange local column information with lower neighbor in Y direction (cart
440 // grid)
441 MPI_Irecv(vertices_rem, 2 * this->global_dims[0], MPIDataTypeT, rank_right, 0,
442 this->globalComm, &rreq);
443 MPI_Isend(vertices_rem + 2 * this->global_dims[0], 2 * this->global_dims[0],
444 MPIDataTypeT, rank_left, 0, this->globalComm, &sreq);
445
446 // determine the offset in ranks
447 offset_coords[0] = 0;
448 offset_coords[1] = this->local_coords[1] + 1;
449 offset_coords[2] = this->local_coords[2];
450
451 rem_coords[1] = offset_coords[1];
452 rem_coords[2] = offset_coords[2];
453
454 MPI_Cart_rank(this->globalComm, offset_coords, &rank_offset);
455
456 // wait for communication
457 MPI_Wait(&sreq, &sstat);
458 MPI_Wait(&rreq, &rstat);
459
460 // iterate about neighbor borders to determine the neighborship relation
461 nNeighbors.at(3) = 0;
462 for (int x = 0; x < this->global_dims[0]; ++x) {
463 if ((vertices_rem[2 * x] <= vertices_loc[0] &&
464 vertices_loc[0] < vertices_rem[2 * x + 1]) ||
465 (vertices_rem[2 * x] < vertices_loc[1] &&
466 vertices_loc[1] <= vertices_rem[2 * x + 1]) ||
467 (vertices_rem[2 * x] >= vertices_loc[0] &&
468 vertices_loc[0] < vertices_rem[2 * x + 1] &&
469 vertices_loc[1] >= vertices_rem[2 * x + 1])) {
470 nNeighbors.at(3)++;
471 rem_coords[0] = x;
472 MPI_Cart_rank(this->globalComm, rem_coords, &rem_rank);
473 neighbors.push_back(rem_rank);
474 }
475 }
476
477 // barrier to ensure every process concluded the calculations before
478 // overwriting remote borders!
479 MPI_Barrier(this->globalComm);
480
481 // find Z-neighbors to get border information from
482 MPI_Cart_shift(this->globalComm, 2, 1, &rank_left, &rank_right);
483
484 // collect border information from local column
485 vertices_loc[0] = shifted_vertices.at(0)[0];
486 vertices_loc[1] = shifted_vertices.at(1)[0];
487 vertices_loc[2] = shifted_vertices.at(0)[1];
488 vertices_loc[3] = shifted_vertices.at(1)[1];
489
490 MPI_Barrier(this->globalComm);
491
492 MPI_Allgather(vertices_loc, 4, MPIDataTypeT,
493 vertices_rem + 4 * this->global_dims[0] * this->global_dims[1],
494 4, MPIDataTypeT, communicators[2]);
495
496 // exchange local column information with upper neighbor in Z direction (cart
497 // grid)
498 MPI_Irecv(vertices_rem, 4 * this->global_dims[0] * this->global_dims[1],
499 MPIDataTypeT, rank_left, 0, this->globalComm, &rreq);
500 MPI_Isend(vertices_rem + 4 * this->global_dims[0] * this->global_dims[1],
501 4 * this->global_dims[0] * this->global_dims[1], MPIDataTypeT,
502 rank_right, 0, this->globalComm, &sreq);
503
504 // determine the offset in ranks
505 offset_coords[0] = 0;
506 offset_coords[1] = 0;
507 offset_coords[2] = this->local_coords[2] - 1;
508
509 rem_coords[2] = offset_coords[2];
510
511 MPI_Cart_rank(this->globalComm, offset_coords, &rank_offset);
512
513 // wait for communication
514 MPI_Wait(&sreq, &sstat);
515 MPI_Wait(&rreq, &rstat);
516
517 // iterate about neighbor borders to determine the neighborship relation
518 nNeighbors.at(4) = 0;
519 for (int y = 0; y < this->global_dims[1]; ++y) {
520 for (int x = 0; x < this->global_dims[0]; ++x) {
521 if (((vertices_rem[4 * (x + y * this->global_dims[0]) + 2] <=
522 vertices_loc[2] &&
523 vertices_loc[2] <
524 vertices_rem[4 * (x + y * this->global_dims[0]) + 3]) ||
525 (vertices_rem[4 * (x + y * this->global_dims[0]) + 2] <
526 vertices_loc[3] &&
527 vertices_loc[3] <=
528 vertices_rem[4 * (x + y * this->global_dims[0]) + 3]) ||
529 (vertices_rem[4 * (x + y * this->global_dims[0]) + 2] >=
530 vertices_loc[2] &&
531 vertices_loc[2] <
532 vertices_rem[4 * (x + y * this->global_dims[0]) + 3] &&
533 vertices_loc[3] >=
534 vertices_rem[4 * (x + y * this->global_dims[0]) + 3])))
535 if (((vertices_rem[4 * (x + y * this->global_dims[0])] <=
536 vertices_loc[0] &&
537 vertices_loc[0] <
538 vertices_rem[4 * (x + y * this->global_dims[0]) + 1]) ||
539 (vertices_rem[4 * (x + y * this->global_dims[0])] <
540 vertices_loc[1] &&
541 vertices_loc[1] <=
542 vertices_rem[4 * (x + y * this->global_dims[0]) + 1]) ||
543 (vertices_rem[4 * (x + y * this->global_dims[0])] >=
544 vertices_loc[0] &&
545 vertices_loc[0] <
546 vertices_rem[4 * (x + y * this->global_dims[0]) + 1] &&
547 vertices_loc[1] >=
548 vertices_rem[4 * (x + y * this->global_dims[0]) + 1]))) {
549 nNeighbors.at(4)++;
550 rem_coords[1] = y;
551 rem_coords[0] = x;
552 MPI_Cart_rank(this->globalComm, rem_coords, &rem_rank);
553 neighbors.push_back(rem_rank);
554 }
555 }
556 }
557
558 // barrier to ensure every process concluded the calculations before
559 // overwriting remote borders!
560 MPI_Barrier(this->globalComm);
561
562 // exchange local column information with upper neighbor in Y direction (cart
563 // grid)
564 MPI_Irecv(vertices_rem, 4 * this->global_dims[0] * this->global_dims[1],
565 MPIDataTypeT, rank_right, 0, this->globalComm, &rreq);
566 MPI_Isend(vertices_rem + 4 * this->global_dims[0] * this->global_dims[1],
567 4 * this->global_dims[0] * this->global_dims[1], MPIDataTypeT,
568 rank_left, 0, this->globalComm, &sreq);
569
570 // determine the offset in ranks
571 offset_coords[0] = 0;
572 offset_coords[1] = 0;
573 offset_coords[2] = this->local_coords[2] + 1;
574
575 rem_coords[2] = offset_coords[2];
576
577 MPI_Cart_rank(this->globalComm, offset_coords, &rank_offset);
578
579 // wait for communication
580 MPI_Wait(&sreq, &sstat);
581 MPI_Wait(&rreq, &rstat);
582
583 // iterate about neighbor borders to determine the neighborship relation
584 nNeighbors.at(5) = 0;
585 for (int y = 0; y < this->global_dims[1]; ++y) {
586 for (int x = 0; x < this->global_dims[0]; ++x) {
587 if (((vertices_rem[4 * (x + y * this->global_dims[0]) + 2] <=
588 vertices_loc[2] &&
589 vertices_loc[2] <
590 vertices_rem[4 * (x + y * this->global_dims[0]) + 3]) ||
591 (vertices_rem[4 * (x + y * this->global_dims[0]) + 2] <
592 vertices_loc[3] &&
593 vertices_loc[3] <=
594 vertices_rem[4 * (x + y * this->global_dims[0]) + 3]) ||
595 (vertices_rem[4 * (x + y * this->global_dims[0]) + 2] >=
596 vertices_loc[2] &&
597 vertices_loc[2] <
598 vertices_rem[4 * (x + y * this->global_dims[0]) + 3] &&
599 vertices_loc[3] >=
600 vertices_rem[4 * (x + y * this->global_dims[0]) + 3])))
601 if (((vertices_rem[4 * (x + y * this->global_dims[0])] <=
602 vertices_loc[0] &&
603 vertices_loc[0] <
604 vertices_rem[4 * (x + y * this->global_dims[0]) + 1]) ||
605 (vertices_rem[4 * (x + y * this->global_dims[0])] <
606 vertices_loc[1] &&
607 vertices_loc[1] <=
608 vertices_rem[4 * (x + y * this->global_dims[0]) + 1]) ||
609 (vertices_rem[4 * (x + y * this->global_dims[0])] >=
610 vertices_loc[0] &&
611 vertices_loc[0] <
612 vertices_rem[4 * (x + y * this->global_dims[0]) + 1] &&
613 vertices_loc[1] >=
614 vertices_rem[4 * (x + y * this->global_dims[0]) + 1]))) {
615 nNeighbors.at(5)++;
616 rem_coords[1] = y;
617 rem_coords[0] = x;
618 MPI_Cart_rank(this->globalComm, rem_coords, &rem_rank);
619 neighbors.push_back(rem_rank);
620 }
621 }
622 }
623
624 // barrier to ensure every process concluded the calculations before
625 // overwriting remote borders!
626 MPI_Barrier(this->globalComm);
627
628 // clear up vertices array
629 delete[] vertices_loc;
630 delete[] vertices_rem;
631}
632
633// provide list of neighbors
634template <class T, class W>
636 return neighbors;
637}
638
639}//namespace ALL
640
641#endif
642// vim: sw=2 et ts=2
#define known_unused
Definition ALL_Defines.h:49
LB(const int dim, const T g)
Definition ALL_LB.hpp:50
virtual void setVertices(const std::vector< Point< T > > &vertices_in)
Definition ALL_LB.hpp:77
int localRank
local rank in the used MPI communicator
Definition ALL_LB.hpp:229
std::vector< W > work
local work
Definition ALL_LB.hpp:236
MPI_Comm globalComm
used MPI communicator
Definition ALL_LB.hpp:227
int dimension
dimension of the used vertices
Definition ALL_LB.hpp:225
std::vector< int > global_dims
dimensions of the global process grid
Definition ALL_LB.hpp:242
virtual void setWork(const std::vector< W > &w)
Definition ALL_LB.hpp:121
bool gammaAutoCalc
turn on/off autocalculation of gamma factor if present
Definition ALL_LB.hpp:223
T gamma
correction factor
Definition ALL_LB.hpp:221
virtual int getDimension()
Definition ALL_LB.hpp:100
std::vector< int > local_coords
cartesian coordinates of the local domain in the process grid
Definition ALL_LB.hpp:244
std::vector< Point< T > > prevVertices
original vertices before previous balancing step
Definition ALL_LB.hpp:240
std::vector< Point< T > > vertices
local vertices after previous balancing step
Definition ALL_LB.hpp:238
~Staggered_LB()
default destructor
virtual void setAdditionalData(known_unused const void *data) override
void balance(int step) override
virtual W getEstimatedEfficiency() override
Staggered_LB(int d, W w, T g)
Staggered_LB()
default constructor
void setup() override
method to setup the method specific internal parameters
virtual std::vector< int > & getNeighbors() override
T borderShift1d(const int remote_rank, const int local_coord, const int global_dim, const W local_work, const W remote_work, const T local_size, const T remote_size, const T gamma, const T minSize)
Definition ALL.hpp:78