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 */
19template<unsigned int dim, typename T, typename Memory, template<typename> class layout_base>
20class 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
121public:
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