OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
MethodOfImages.hpp
1 //
2 // Created by jstark on 01.06.21.
3 //
4 
5 #ifndef OPENFPM_NUMERICS_BOUNDARYCONDITIONS_METHODOFIMAGES_HPP
6 #define OPENFPM_NUMERICS_BOUNDARYCONDITIONS_METHODOFIMAGES_HPP
7 
8 #include <cmath>
9 // Include OpenFPM header files
10 #include "Vector/vector_dist_subset.hpp"
11 
12 #define PID_VECTOR_TYPE openfpm::vector<aggregate<int>>
13 #define KEY_VECTOR_TYPE openfpm::vector<vect_dist_key_dx>
14 
24 template <size_t SurfaceNormal, typename vd_type>
26 
27 public:
30 
38  vd_type & vd,
39  const KEY_VECTOR_TYPE & keys_source,
40  const size_t subset_id_real = 0,
41  const size_t subset_id_mirror = 1)
45  , Real(vd, subset_id_real)
47 
48  {
49 #ifdef SE_CLASS1
51 #endif // SE_CLASS1
52  }
53 
54  // Member variables
55  size_t subset_id_real;
57  KEY_VECTOR_TYPE keys_source;
58  PID_VECTOR_TYPE pid_mirror;
60  vd_subset_type Real;
61  openfpm::vector<openfpm::vector<size_t>> key_map_source_mirror;
62 
67  void get_mirror_particles(vd_type & vd)
68  {
69  auto lastReal = vd.size_local();
70  for (int i = 0; i < keys_source.size(); i++)
71  {
72  auto key_source = keys_source.get(i);
73 
74  size_t id_source = key_source.getKey();
75  size_t id_mirror = lastReal + i;
76 
77  point_type xp = vd.getPos(key_source);
78  point_type n = vd.template getProp<SurfaceNormal>(key_source);
79  point_type xm = xp + 2 * n;
80 
81 #ifdef SE_CLASS1
82  if(!point_lies_on_this_processor(vd, xm))
83  {
84  std::cerr << __FILE__ << ":" << __LINE__ << " Error: Ghost layer is too small. Source and mirror"
85  " particles that belong together must lie on the same"
86  " processor."
87  " Create a bigger ghost layer which is bigger than the"
88  " mirror particle layer. Aborting..." << std::endl;
89  abort();
90  }
91 #endif // SE_CLASS1
92 
93  vd.add();
94  for (size_t d = 0; d < vd_type::dims; d++)
95  {
96  vd.getLastPos()[d] = xm[d];
97  }
98  vd.getLastSubset(subset_id_mirror);
99  openfpm::vector<size_t> pair = {id_source, id_mirror};
100  key_map_source_mirror.add(pair);
101  }
102  // No vd.map() since this would change the IDs of the particles and then we wouldn't know which source and
103  // which mirror belong to each other
104  vd.template ghost_get();
106  Mirror.update();
108 
109 #ifdef SE_CLASS1
110  check_size_mirror_source_equal();
111 #endif // SE_CLASS1
112  }
113 
114 
120  template <size_t PropToMirror>
121  void apply_noflux(vd_type & vd)
122  {
123  vd.template ghost_get<PropToMirror>(KEEP_PROPERTIES); // Update Ghost layer.
124 
125  for(int i = 0; i < key_map_source_mirror.size(); ++i)
126  {
127  openfpm::vector<size_t> row = key_map_source_mirror.get(i);
128  vect_dist_key_dx key_source, key_mirror;
129  key_source.setKey(row.get(0));
130  key_mirror.setKey(row.get(1));
131  vd.template getProp<PropToMirror>(key_mirror) = vd.template getProp<PropToMirror>(key_source);
132  }
133  }
134 
135 
136 private:
143  void check_if_ghost_isometric(vd_type & vd)
144  {
145  for(int d=0; d<vd_type::dims; d++)
146  {
147  if (vd.getDecomposition().getGhost().getLow(0) != vd.getDecomposition().getGhost().getLow(d))
148  {
149  std::cerr << __FILE__ << ":" << __LINE__ << "Ghost layer doesn't have the same size in all dimensions"
150  ". Use an isometric ghost layer. Aborting..."
151  << std::endl;
152  abort();
153  }
154  }
155  }
156 #ifdef SE_CLASS1
157 
165  bool point_lies_on_this_processor(vd_type & vd, point_type p)
166  {
167  double g_width = fabs(vd.getDecomposition().getGhost().getLow(0));
169 
170  auto & subs = vd.getDecomposition().getSubDomains();
171 
172  bool is_inside = false;
173 
174  for (int i = 0 ; i < subs.size() ; i++)
175  {
177  sub.enlarge(g);
178  is_inside |= sub.isInside(p);
179  }
180 
181  if (!is_inside) {std::cout << "Processor does not have the point" << std::endl;}
182 
183  return is_inside;
184  }
185 
189  void check_size_mirror_source_equal()
190  {
191  if (pid_mirror.size() != keys_source.size())
192  {
193  std::cout << "pid_mirror.size() = " << pid_mirror.size() << ", keys_source.size() = " << keys_source.size()
194  << std::endl;
195  std::cerr << __FILE__ << ":" << __LINE__
196  << " Error: Local vector of source-IDs has different size than local vector of mirror-IDs. Matching "
197  "source and mirror particle IDs must be stored on same processor." << std::endl;
198  abort();
199  }
200  }
201 #endif // SE_CLASS1
202 
203 };
204 
205 
206 
207 
208 #endif //OPENFPM_NUMERICS_BOUNDARYCONDITIONS_METHODOFIMAGES_HPP
void get_mirror_particles(vd_type &vd)
Place mirror particles along the surface normal.
This class represent an N-dimensional box.
Definition: SpaceBox.hpp:26
openfpm::vector< aggregate< int > > & getIds()
Return the ids.
size_t subset_id_real
ID of subset containing the real particles (default=0).
Class for getting mirror particles to impose Neumann BCs.
__device__ __host__ void setKey(size_t key)
set the key
This class implement the point shape in an N-dimensional space.
Definition: Point.hpp:27
Grid key for a distributed grid.
__host__ __device__ bool isInside(const Point< dim, T > &p) const
Check if the point is inside the box.
Definition: Box.hpp:1004
size_t size()
Stub size.
Definition: map_vector.hpp:211
size_t subset_id_mirror
ID of subset containing the mirror particles (default=1).
Definition: Ghost.hpp:39
MethodOfImages(vd_type &vd, const KEY_VECTOR_TYPE &keys_source, const size_t subset_id_real=0, const size_t subset_id_mirror=1)
Constructor.
void enlarge(const Box< dim, T > &gh)
Enlarge the box with ghost margin.
Definition: Box.hpp:823
void apply_noflux(vd_type &vd)
Copies the values stored in PropToMirror from each source particle to its respective mirror particles...
PID_VECTOR_TYPE pid_mirror
Vector containing indices of mirror particles.
KEY_VECTOR_TYPE keys_source
Vector containing keys of source particles.
void check_if_ghost_isometric(vd_type &vd)
Checks if the ghost layer has the same size in all dimensions. This is required to ensure that the gh...
void update()
Update the subset indexes.
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:202
vd_subset_type Mirror
Subset containing the mirror particles.