OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
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
24template <size_t SurfaceNormal, typename vd_type>
26
27public:
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
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
136private:
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
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
__host__ __device__ bool isInside(const Point< dim, T > &p) const
Check if the point is inside the box.
Definition Box.hpp:1004
void enlarge(const Box< dim, T > &gh)
Enlarge the box with ghost margin.
Definition Box.hpp:823
Class for getting mirror particles to impose Neumann BCs.
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...
vd_subset_type Mirror
Subset containing the mirror particles.
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 get_mirror_particles(vd_type &vd)
Place mirror particles along the surface normal.
size_t subset_id_real
ID of subset containing the real particles (default=0).
PID_VECTOR_TYPE pid_mirror
Vector containing indices of mirror particles.
KEY_VECTOR_TYPE keys_source
Vector containing keys of source particles.
void apply_noflux(vd_type &vd)
Copies the values stored in PropToMirror from each source particle to its respective mirror particles...
size_t subset_id_mirror
ID of subset containing the mirror particles (default=1).
This class implement the point shape in an N-dimensional space.
Definition Point.hpp:28
This class represent an N-dimensional box.
Definition SpaceBox.hpp:27
Implementation of 1-D std::vector like structure.
size_t size()
Stub size.
Grid key for a distributed grid.
__device__ __host__ void setKey(size_t key)
set the key
void update()
Update the subset indexes.
openfpm::vector< aggregate< int > > & getIds()
Return the ids.