ls1-MarDyn
ls1-MarDyn molecular dynamics code
CellBorderAndFlagManager.h
1/*
2 * CellBorderManager.h
3 *
4 * Created on: 10 Oct 2017
5 * Author: tchipevn
6 */
7
8#ifndef SRC_PARTICLECONTAINER_CELLBORDERANDFLAGMANAGER_H_
9#define SRC_PARTICLECONTAINER_CELLBORDERANDFLAGMANAGER_H_
10
11#include <array>
12#include <vector>
13
14#include "utils/mardyn_assert.h"
15#include "utils/threeDimensionalMapping.h"
16
17// TODO: use in LinkedCells::initializeCells
18
20public:
21 typedef unsigned long GlobalLinearizedIndex_t;
22 typedef unsigned long Global1DIndex_t;
23 typedef std::array<Global1DIndex_t, 3> Global3DIndex_t;
24 enum class IsCell_t { HALO = 0, BOUNDARY = 1, INNER = 2, INNERMOST = 3};
25
26 CellBorderAndFlagManager() : _initCalled(false) {}
27
28 void init(int cellsPerDim[3],
29 double haloBoxMin[3], double haloBoxMax[3],
30 double boxMin[3], double boxMax[3],
31 double cellLength[3], int haloWidthInNumCells[3]) {
32 int totalNumCells = 1;
33 for (int d = 0; d < 3; ++d) {
34 _cellsPerDimension[d] = cellsPerDim[d];
35 _haloBoundingBoxMin[d] = haloBoxMin[d];
36 _haloBoundingBoxMax[d] = haloBoxMax[d];
37 _boundingBoxMin[d] = boxMin[d];
38 _boundingBoxMax[d] = boxMax[d];
39 _cellLength[d] = cellLength[d];
40 _haloWidthInNumCells[d] = haloWidthInNumCells[d];
41
42 totalNumCells *= cellsPerDim[d];
43 }
44
45 _haloCellFlags.resize(totalNumCells);
46
47 int runningIndex = 0;
48
49 for (unsigned z = 0; z < _cellsPerDimension[2]; ++z) {
50 bool isHaloZ = (z < _haloWidthInNumCells[2] or z >= _cellsPerDimension[2] - _haloWidthInNumCells[2]);
51
52 for (unsigned y = 0; y < _cellsPerDimension[1]; ++y) {
53 bool isHaloY = (y < _haloWidthInNumCells[1] or y >= _cellsPerDimension[1] - _haloWidthInNumCells[1]);
54
55 for (unsigned x = 0; x < _cellsPerDimension[0]; ++x) {
56 bool isHaloX =
57 (x < _haloWidthInNumCells[0] or x >= _cellsPerDimension[0] - _haloWidthInNumCells[0]);
58
59 if (isHaloZ or isHaloY or isHaloX) {
60 _haloCellFlags.at(runningIndex) = true;
61 } else {
62 _haloCellFlags.at(runningIndex) = false;
63 }
64 runningIndex++;
65 }
66 }
67 }
68 _initCalled = true;
69 }
70
71 // NOTE: optimised isHaloCell for runtime. Uses 1 bit per cell.
72 //
73 // old attempts:
74 // * storing bool-s per dimension and computing isHaloCell as a tensor product
75 // * simplifying the logic
76 // but neither brought any visible acceleration (tested in RMM mode with low density and low cutoff).
77 // One could also try to reduce the number of calls to isHaloCell().
78// bool isHaloCell(GlobalLinearizedIndex_t cellIndex) const { return isCell(IsCell_t::HALO, cellIndex); } // <- this still works
79 bool isHaloCell(GlobalLinearizedIndex_t cellIndex) const {
80 return _haloCellFlags[cellIndex];
81 }
82 bool isBoundaryCell(GlobalLinearizedIndex_t cellIndex) const { return isCell(IsCell_t::BOUNDARY, cellIndex); }
83 bool isInnerCell(GlobalLinearizedIndex_t cellIndex) const { return isCell(IsCell_t::INNER, cellIndex); }
84 bool isInnerMostCell(GlobalLinearizedIndex_t cellIndex) const { return isCell(IsCell_t::INNERMOST, cellIndex); }
85
86 double getBoundingBoxMin(GlobalLinearizedIndex_t cellIndex, int dimension) const {
87 Global3DIndex_t r = rIndex(cellIndex);
88 Global1DIndex_t indexInDimension = r[dimension];
89 return getBorder(indexInDimension, dimension);
90 }
91
92 double getBoundingBoxMax(GlobalLinearizedIndex_t cellIndex, int dimension) const {
93 Global3DIndex_t r = rIndex(cellIndex);
94 Global1DIndex_t indexInDimension = r[dimension];
95 return getBorder(indexInDimension + 1, dimension);
96 }
97
98private:
99 bool isCell(IsCell_t type, GlobalLinearizedIndex_t cellIndex) const {
100 bool ret;
101 Global3DIndex_t r = rIndex(cellIndex);
102 if (type == IsCell_t::HALO or type == IsCell_t::BOUNDARY) {
103 ret = false;
104 for (int d = 0; d < 3; ++d) {
105 ret |= isCell1D(type, r[d], d);
106 }
107 } else {
108 ret = true;
109 for (int d = 0; d < 3; ++d) {
110 ret &= isCell1D(type, r[d], d);
111 }
112 }
113 return ret;
114 }
115 bool isCell1D(IsCell_t type, Global1DIndex_t index, int dimension) const {
116 mardyn_assert(_initCalled);
117 bool ret;
118 switch(type) {
119 case IsCell_t::HALO:
120 ret = (index == 0) or (index == _cellsPerDimension[dimension]-1);
121 break;
122 case IsCell_t::BOUNDARY:
123 ret = (index == 1) or (index == _cellsPerDimension[dimension]-2);
124 break;
125 case IsCell_t::INNER:
126 ret = (index >= 2) and (index <= _cellsPerDimension[dimension]-3);
127 break;
128 case IsCell_t::INNERMOST:
129 ret = (index >= 3) and (index <= _cellsPerDimension[dimension]-4);
130 break;
131 }
132 return ret;
133 }
134 double getBorder(Global1DIndex_t index, int dimension) const {
135 mardyn_assert(_initCalled);
136 mardyn_assert(index <= _cellsPerDimension[dimension]);
137
138 double ret;
139 // why oh why don't we have switch statements on variables
140 if (index == 0) {
141 ret = _haloBoundingBoxMin[dimension];
142 } else if (index == _haloWidthInNumCells[dimension]) {
143 ret = _boundingBoxMin[dimension];
144 } else if (index == _cellsPerDimension[dimension] - _haloWidthInNumCells[dimension]) {
145 ret = _boundingBoxMax[dimension];
146 } else if (index == _cellsPerDimension[dimension]) {
147 ret = _haloBoundingBoxMax[dimension];
148 } else {
149 ret = index * _cellLength[dimension] + _haloBoundingBoxMin[dimension];
150 }
151 return ret;
152 }
153
154 Global3DIndex_t rIndex(GlobalLinearizedIndex_t index) const {
155 return threeDimensionalMapping::oneToThreeD(index, _cellsPerDimension);
156 }
157
158 //member fields
159 bool _initCalled;
160 Global3DIndex_t _cellsPerDimension;
161 std::array<double, 3> _boundingBoxMin, _boundingBoxMax;
162 std::array<double, 3> _haloBoundingBoxMin, _haloBoundingBoxMax;
163 std::array<double, 3> _cellLength;
164 std::array<int, 3> _haloWidthInNumCells;
165
166 // is (should be) space-optimised by compiler to store 1 bit per entry, instead of 1 byte.
167 std::vector<bool> _haloCellFlags;
168
169};
170
171#endif /* SRC_PARTICLECONTAINER_CELLBORDERANDFLAGMANAGER_H_ */
Definition: CellBorderAndFlagManager.h:19
Enumeration class corresponding to the type schema type.
Definition: vtk-unstructured.h:1746