1 | /* |
2 | * shift_vect_converter.hpp |
3 | * |
4 | * Created on: Feb 8, 2018 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef SRC_DECOMPOSITION_SHIFT_VECT_CONVERTER_HPP_ |
9 | #define SRC_DECOMPOSITION_SHIFT_VECT_CONVERTER_HPP_ |
10 | |
11 | #include "Space/Shape/HyperCube.hpp" |
12 | |
13 | /*! \brief in case of high dimensions shift vector converter |
14 | * |
15 | * In case of high-dimensions the number of shift vectors explode, this class |
16 | * handle such case |
17 | * |
18 | */ |
19 | template<unsigned int dim, typename T, typename Memory, template<typename> class layout_base> |
20 | class shift_vect_converter |
21 | { |
22 | //! Indicate which indexes are non_periodic |
23 | size_t red_shift_v[dim]; |
24 | |
25 | // indexes |
26 | size_t tmp[dim]; |
27 | |
28 | // Dimension |
29 | int dim_r = 0; |
30 | |
31 | /*! \brief Here we generare the shift vectors for the low dimension case |
32 | * |
33 | * \param domain box that describe the domain |
34 | * |
35 | */ |
36 | void generateShiftVectors_ld(const Box<dim,T> & domain, size_t (& bc)[dim], |
37 | openfpm::vector<Point<dim,T>,Memory,layout_base> & shifts) |
38 | { |
39 | shifts.resize(openfpm::math::pow(3,dim)); |
40 | |
41 | HyperCube<dim> hyp; |
42 | |
43 | for (long int i = dim ; i >= 0 ; i--) |
44 | { |
45 | std::vector<comb<dim>> cmbs = hyp.getCombinations_R(i); |
46 | |
47 | for (size_t j = 0 ; j < cmbs.size() ; j++) |
48 | { |
49 | for (size_t k = 0 ; k < dim ; k++) |
50 | { |
51 | switch (cmbs[j][k]) |
52 | { |
53 | case 1: |
54 | shifts.get(cmbs[j].lin()).template get<0>()[k] = -(domain.getHigh(k) - domain.getLow(k)); |
55 | break; |
56 | case 0: |
57 | shifts.get(cmbs[j].lin()).template get<0>()[k] = 0; |
58 | break; |
59 | case -1: |
60 | shifts.get(cmbs[j].lin()).template get<0>()[k] = (domain.getHigh(k) - domain.getLow(k)); |
61 | break; |
62 | } |
63 | } |
64 | } |
65 | } |
66 | } |
67 | |
68 | /*! \brief Here we generare the shift vectors for the high dimension case |
69 | * |
70 | * \param domain box that describe the domain |
71 | * |
72 | */ |
73 | void generateShiftVectors_hd(const Box<dim,T> & domain, size_t (& bc)[dim], |
74 | openfpm::vector<Point<dim,T>,Memory,layout_base> & shifts) |
75 | { |
76 | // get the indexes of the free degree of freedom |
77 | for (size_t i = 0 ; i < dim ; i++) |
78 | { |
79 | if (bc[i] == PERIODIC) |
80 | { |
81 | red_shift_v[dim_r] = i; |
82 | dim_r++; |
83 | } |
84 | } |
85 | |
86 | HyperCube<dim> hyp; |
87 | |
88 | // precalculate the nuber of shift vectors |
89 | size_t nsv = 0; |
90 | for (long int i = dim-1 ; i >= 0 ; i--) |
91 | {nsv += hyp.getCombinations_R_bc(i,bc).size();} |
92 | shifts.resize(nsv+1); |
93 | |
94 | for (long int i = dim-1 ; i >= 0 ; i--) |
95 | { |
96 | std::vector<comb<dim>> cmbs = hyp.getCombinations_R_bc(i,bc); |
97 | |
98 | for (size_t j = 0 ; j < cmbs.size() ; j++) |
99 | { |
100 | size_t lin_cmb = linId_hd(cmbs[j]); |
101 | |
102 | for (size_t k = 0 ; k < dim ; k++) |
103 | { |
104 | switch (cmbs[j][k]) |
105 | { |
106 | case 1: |
107 | shifts.get(lin_cmb).template get<0>()[k] = -(domain.getHigh(k) - domain.getLow(k)); |
108 | break; |
109 | case 0: |
110 | shifts.get(lin_cmb).template get<0>()[k] = 0; |
111 | break; |
112 | case -1: |
113 | shifts.get(lin_cmb).template get<0>()[k] = (domain.getHigh(k) - domain.getLow(k)); |
114 | break; |
115 | } |
116 | } |
117 | } |
118 | } |
119 | } |
120 | |
121 | public: |
122 | |
123 | /*! \brief Here we generare the shift vectors for the low dimension case |
124 | * |
125 | * \param domain box that describe the domain |
126 | * |
127 | */ |
128 | void generateShiftVectors(const Box<dim,T> & domain, size_t (& bc)[dim], |
129 | openfpm::vector<Point<dim,T>,Memory,layout_base> & shifts) |
130 | { |
131 | if (dim < 10) |
132 | {generateShiftVectors_ld(domain,bc,shifts);} |
133 | else |
134 | {generateShiftVectors_hd(domain,bc,shifts);} |
135 | } |
136 | |
137 | /*! \brief Initialize |
138 | * |
139 | * \param bc boundary conditions |
140 | * |
141 | */ |
142 | void Initialize(size_t (& bc)[dim]) |
143 | { |
144 | // get the indexes of the free degree of freedom |
145 | for (size_t i = 0 ; i < dim ; i++) |
146 | { |
147 | if (bc[i] == PERIODIC) |
148 | { |
149 | red_shift_v[dim] = i; |
150 | dim_r++; |
151 | } |
152 | } |
153 | } |
154 | |
155 | /*! \brief linearize the combination in case of high dimension |
156 | * |
157 | * \param cmb combination |
158 | * |
159 | */ |
160 | size_t linId_hd(const comb<dim> & cmb) |
161 | { |
162 | size_t cul = 1; |
163 | size_t lin = 0; |
164 | for (long int i = 0 ; i < dim_r ; i++) |
165 | { |
166 | lin += cul*(cmb.c[red_shift_v[i]] + 1); |
167 | cul *= 3; |
168 | } |
169 | |
170 | return lin; |
171 | } |
172 | |
173 | /*! \brief linearize the combination in case of low dimensions |
174 | * |
175 | * \param cmb combination |
176 | * |
177 | */ |
178 | inline size_t linId_ld(const comb<dim> & cmb) |
179 | { |
180 | return cmb.lin(); |
181 | } |
182 | |
183 | /*! \brief linearize the combination in case of high dimensions |
184 | * |
185 | * \param cmb combination |
186 | * |
187 | */ |
188 | inline size_t linId(const comb<dim> & cmb) |
189 | { |
190 | if (dim < 10) |
191 | {return linId_ld(cmb);} |
192 | |
193 | return linId_hd(cmb); |
194 | } |
195 | |
196 | }; |
197 | |
198 | |
199 | #endif /* SRC_DECOMPOSITION_SHIFT_VECT_CONVERTER_HPP_ */ |
200 | |