OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
 
Loading...
Searching...
No Matches
auxFunc.hpp
1// ------------------------------------------------------------------------------------------
2// ActiveGelsOnDeformableSurfaces
3// Copyright (C) 2020 ---- foggia
4//
5// This file is part of the ActiveGelsOnDeformableSurfaces software.
6//
7// This program is free software: you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation, either version 3 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program. If not, see <http://www.gnu.org/licenses/>.
19// ------------------------------------------------------------------------------------------
20//
21// Created by foggia on 22-04-11
22//
23
24
25// 1) Function to compute analytically the SDF and the normal for the sphere in the whole domain
26template <typename grid_type, int SDF, int normal>
27void init_surfaceAndNormal(grid_type & grid,
28 const std::array<double,grid_type::dims> & center,
29 const double radius) {
30
31 const int x{0};
32 const int y{1};
33 const int z{2};
34 double dist, arg, theta, phi;
35 std::array<double, grid_type::dims> coord;
36
37 auto it = grid.getDomainIterator();
38 while(it.isNext()) {
39 auto key = it.get();
40
41 dist = 0;
42 for (int d = 0; d < grid_type::dims; ++d) {
43 coord[d] = grid.getPos(key)[d];
44 dist += (coord[d]-center[d])*(coord[d]-center[d]);
45 }
46 arg = (coord[x]-center[x]) * (coord[x]-center[x]) + (coord[y]-center[y]) * (coord[y]-center[y]);
47 theta = std::atan2(std::sqrt(arg),(coord[z]-center[z]));
48 phi = std::atan2((coord[y]-center[y]),(coord[x]-center[x]));
49
50 grid.template get<SDF>(key) = std::sqrt(dist) - radius;
51 grid.template get<normal>(key)[x] = std::sin(theta)*std::cos(phi);
52 grid.template get<normal>(key)[y] = std::sin(theta)*std::sin(phi);
53 grid.template get<normal>(key)[z] = std::cos(theta);
54
55 ++it;
56 }
57}
58
59// 2) Function to compute analytically the SDF and the normal for the sphere in the whole domain
60template <typename grid_type, int SDF>
61void init_surface(grid_type & grid,
62 const std::array<double,grid_type::dims> & center,
63 const double radius) {
64
65 double dist;
66 std::array<double, grid_type::dims> coord;
67
68 auto it = grid.getDomainIterator();
69 while(it.isNext()) {
70 auto key = it.get();
71
72 dist = 0;
73 for (int d = 0; d < grid_type::dims; ++d) {
74 coord[d] = grid.getPos(key)[d];
75 dist += (coord[d]-center[d])*(coord[d]-center[d]);
76 }
77
78 grid.template get<SDF>(key) = std::sqrt(dist) - radius;
79 ++it;
80 }
81}
82
83// 3a) Function to initialize the value of the quantity (spherical harmonic (4,0)) on the narrow band
84// Y(4,0) = 3/16 * sqrt(1/pi) * (35*cos^4(theta) - 30*cos^2(theta) + 3)
85template <typename grid_type, int qty, typename key_type>
86void init_qty(grid_type & grid,
87 const std::array<double,grid_type::dims> & center,
88 std::vector<key_type> & nb_keys) {
89
90 const int x{0};
91 const int y{1};
92 const int z{2};
93 double arg, theta, cos2;
94 const double pi{3.14159265358979323846};
95 const double prefactor{3.0/16.0 * std::sqrt(1.0/pi)};
96 std::array<double,grid.dims> coord;
97
98 for (int i = 0; i < nb_keys.size(); ++i) {
99
100 for (int d = 0; d < grid.dims; ++d)
101 coord[d] = grid.getPos(nb_keys[i])[d];
102
103 arg = (coord[x]-center[x]) * (coord[x]-center[x]) + (coord[y]-center[y]) * (coord[y]-center[y]);
104 theta = std::atan2(std::sqrt(arg),(coord[z]-center[z]));
105 cos2 = std::cos(theta)*std::cos(theta);
106
107 grid.template get<qty>(nb_keys[i]) = prefactor * (cos2*(35.0*cos2 - 30.0) + 3.0);
108
109 }
110}
111
112// 3b) Function to initialize the value of the quantity (spherical harmonic (4,0)) on the whole grid
113// Y(4,0) = 3/16 * sqrt(1/pi) * (35*cos^4(theta) - 30*cos^2(theta) + 3)
114template <typename grid_type, int qty>
115void init_qty(grid_type & grid,
116 const std::array<double,grid_type::dims> & center) {
117
118 const int x{0};
119 const int y{1};
120 const int z{2};
121 double arg, theta, cos2;
122 const double pi{3.14159265358979323846};
123 const double prefactor{3.0/16.0 * std::sqrt(1.0/pi)};
124 std::array<double,grid.dims> coord;
125
126 auto it = grid.getDomainIterator();
127 while(it.isNext()) {
128 auto key = it.get();
129
130 for (int d = 0; d < grid.dims; ++d)
131 coord[d] = grid.getPos(key)[d];
132
133 arg = (coord[x]-center[x]) * (coord[x]-center[x]) + (coord[y]-center[y]) * (coord[y]-center[y]);
134 theta = std::atan2(std::sqrt(arg),(coord[z]-center[z]));
135 cos2 = std::cos(theta)*std::cos(theta);
136
137 grid.template get<qty>(key) = prefactor * (cos2*(35.0*cos2 - 30.0) + 3.0);
138 ++it;
139 }
140}
141// 4) Function to compute the analytical solution of the LB operator in the whole domain
142template <typename grid_type, int qty, int sol>
143void init_analytSol(grid_type & grid,
144 const std::array<double,grid_type::dims> & center,
145 const double radius) {
146
147 const int x{0};
148 const int y{1};
149 const int z{2};
150 double arg, theta, cos2;
151 const double pi{3.14159265358979323846};
152 const double prefactor{3.0/16.0 * std::sqrt(1.0/pi)};
153 std::array<double,grid.dims> coord;
154
155 auto it = grid.getDomainIterator();
156 while(it.isNext()) {
157 auto key = it.get();
158
159 for (int d = 0; d < grid.dims; ++d)
160 coord[d] = grid.getPos(key)[d];
161
162 arg = (coord[x]-center[x]) * (coord[x]-center[x]) + (coord[y]-center[y]) * (coord[y]-center[y]);
163 theta = std::atan2(std::sqrt(arg),(coord[z]-center[z]));
164 cos2 = std::cos(theta)*std::cos(theta);
165
166 grid.template get<sol>(key) = -20.0 * prefactor * (cos2*(35.0*cos2 - 30.0) + 3.0);
167 ++it;
168 }
169}
170
171// 5) Functions to get the points on a NB around the surface (from jstark - Sussman code)
172bool within_narrow_band(double phi,
173 double b_low,
174 double b_up) {
175 return (phi >= b_low && phi <= b_up);
176}
177
178template<typename grid_type, size_t prop, typename key_type>
179void get_NB_indices(grid_type & grid,
180 double thickness, // NOT grid points
181 std::vector<key_type> & nb_keys) {
182
183 double b_low = -thickness/2.0;
184 double b_up = thickness/2.0;
185
186 auto it{grid.getDomainIterator()};
187 while (it.isNext()) {
188
189 auto key{it.get()};
190 if (within_narrow_band(grid.template get<prop>(key),b_low,b_up))
191 nb_keys.push_back(key);
192 ++it;
193 }
194}
195
196// 6) Functions to compute the L2 and Linf norms (from jstark)
197struct L_norms {
198 double l2;
199 double linf;
200};
201
202template<typename grid_type, int PropNumeric, int PropAnalytic, int Error, typename key_type>
204 std::vector<key_type> & nb_keys) {
205 for (int i = 0; i < nb_keys.size(); ++i)
206 grid.template getProp<Error>(nb_keys[i]) = std::fabs(grid.template getProp<PropAnalytic>(nb_keys[i]) - (grid.template getProp<PropNumeric>(nb_keys[i])));
207}
208
209template<typename grid_type, int error, typename key_type>
210L_norms get_l_norms_NB(grid_type & grid,
211 std::vector<key_type> & nb_keys) {
212
213 double maxError{0};
214 double sumErrorSq{0};
215 size_t num_nb{nb_keys.size()};
216
217 for (int i = 0; i < nb_keys.size(); ++i) {
218
219 sumErrorSq += grid.template getProp<error>(nb_keys[i]) * grid.template getProp<error>(nb_keys[i]);
220 if (grid.template getProp<error>(nb_keys[i]) > maxError)
221 maxError = grid.template getProp<error>(nb_keys[i]); // update maxError
222 }
223
224 // Communicate between processes
225 auto &v_cl = create_vcluster();
226 v_cl.sum(num_nb);
227 v_cl.sum(sumErrorSq);
228 v_cl.max(maxError);
229 v_cl.execute();
230
231 double l2{std::sqrt(sumErrorSq / (double)num_nb)};
232 // std::cout << "sum of num_nb: " << (double)num_nb << "\n";
233 double linf{maxError};
234 return {l2, linf};
235}
236
237template<typename T>
238void write_lnorms_to_file(T N, L_norms l_norms, std::string filename, std::string path_output) {
239 auto &v_cl = create_vcluster();
240 if (v_cl.rank() == 0) {
241 std::string path_output_lnorm{path_output + "/" + filename + ".csv"};
242 create_file_if_not_exist(path_output_lnorm);
243
244 std::ofstream l_out;
245 l_out.open(path_output_lnorm, std::ios::app); // append instead of overwrite
246 l_out << N << ',' << std::setprecision(6) << std::scientific << l_norms.l2 << ',' << l_norms.linf
247 << std::endl;
248 l_out.close();
249 }
250}
251
252// Function to set particle property to zero
253template<typename vector_type, int prop>
254void set_prop2zero(vector_type & vec) {
255 auto it = vec.getDomainIterator();
256
257 while (it.isNext()) {
258 auto key = it.get();
259 vec.template getProp<prop>(key) = 0.0;
260 ++it;
261 }
262}
263
264
265// 7) Function to initialize the projection matrix of the surface
266// template<typename grid_type, int normal, int projMat_prop>
267// void init_projMat(grid_type & grid) {
268
269// double ni, nj;
270// auto it{grid.getDomainIterator()};
271// while (it.isNext()) {
272// auto key{it.get()};
273// for (int i = 0; i < DIM; ++i) {
274// ni = grid.template get<normal>(key)[i];
275// for (int j = 0; j < DIM; ++j) {
276// nj = grid.template get<normal>(key)[j];
277// grid.template get<projMat_prop>(key)[i][j] = (i==j)*(1-ni*nj) - !(i==j)*(ni*nj);
278// }
279// }
280// ++it;
281// }
282// }
283
284
285// 8) Function to compute the surface gradient of a quantity
286// template<typename grid_type, int QTY, int GRAD, int SURFGRAD, int PROJMAT, typename DX, typename DY, typename DZ, typename key_type>
287// void SGrad(grid_type & grid,
288// DX & Dx,
289// DY & Dy,
290// DZ & Dz) {
291
292// auto qty{FD::getV<QTY>(grid)};
293// auto grad_qty{FD::getV<GRAD>(grid)};
294
295// grid.template ghost_get<QTY,GRAD,PROJMAT>();
296
297// grad_qty[0] = Dx(qty);
298// grad_qty[1] = Dy(qty);
299// grad_qty[2] = Dz(qty);
300
301// // Projection
302// auto it{grid.getDomainIterator()};
303// while (it.isNext()) {
304
305// auto key{it.get()};
306
307// for (int l = 0; l < DIM; ++l)
308// for (int k = 0; k < DIM; ++k)
309// for (int t = 0; t < DIM; ++t)
310// for (int h = 0; h < DIM; ++h)
311// grid.template get<SURFGRAD>(key)[l][k] += grid.template get<PROJMAT>(key)[l][t] * grid.template get<PROJMAT>(key)[k][h] * grid.template get<EUCGRAD>(key)[t][h];
312// ++it;
313// }
314
315// }
void get_absolute_error(gridtype &grid)
At each grid node, the absolute error is computed and stored in another property.
Definition LNorms.hpp:43
static void create_file_if_not_exist(std::string path)
Creates a file if not already existent.
This is a distributed grid.
static const unsigned int dims
Number of dimensions.
vect_dist_key_dx get()
Get the actual key.
Distributed vector.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.