forked from barbagroup/fmm-bem-relaxed
-
Notifications
You must be signed in to change notification settings - Fork 1
/
serialrun_stresslet.cpp
207 lines (180 loc) · 5.68 KB
/
serialrun_stresslet.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/** @file serialun.cpp
* @brief Testing and debugging script
*/
//#define DEBUG
#include <FMM_plan.hpp>
#define STRESSLET
#include "StokesSpherical.hpp"
#include <string.h>
// modify error checking for counting kernel
// TODO: Do this much better...
//#define SKELETON_KERNEL
//#define UNIT_KERNEL
//#define SPH_KERNEL
//#define CART_KERNEL
//#define YUKAWA_KERNEL
//#define YUKAWA_SPH
#define STOKES_SPH
// Random number in [0,1)
inline double drand() {
return ::drand48();
}
// Random number in [A,B)
inline double drand(double A, double B) {
return A + (B-A) * drand();
}
int main(int argc, char **argv)
{
int numBodies = 1000, p=5;
bool checkErrors = true;
double beta = 0.125;
FMMOptions opts = get_options(argc, argv);
// parse custom command line args
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i],"-N") == 0) {
i++;
numBodies = atoi(argv[i]);
} else if (strcmp(argv[i],"-p") == 0) {
i++;
p = atoi(argv[i]);
} else if (strcmp(argv[i],"-beta") == 0) {
i++;
beta = atof(argv[i]);
} else if (strcmp(argv[i],"-nocheck") == 0) {
checkErrors = false;
}
}
// Init the FMM Kernel
#ifdef SKELETON_KERNEL
typedef KernelSkeleton kernel_type;
kernel_type K;
#endif
#ifdef SPH_KERNEL
typedef LaplaceSpherical kernel_type;
kernel_type K(p);
#endif
#ifdef CART_KERNEL
typedef LaplaceCartesian<5> kernel_type;
kernel_type K;
#endif
#ifdef YUKAWA_KERNEL
typedef YukawaCartesian kernel_type;
kernel_type K(p,beta);
#endif
#ifdef YUKAWA_SPH
typedef YukawaSpherical kernel_type;
kernel_type K(p,beta);
#endif
#ifdef UNIT_KERNEL
typedef UnitKernel kernel_type;
kernel_type K;
#endif
#ifdef STOKES_SPH
typedef StokesSpherical kernel_type;
kernel_type K(p);
#endif
// if not using a Yukawa kernel, quiet warnings
#if !defined(YUKAWA_KERNEL) && !defined(YUKAWA_SPH)
(void) beta;
#endif
typedef kernel_type::point_type point_type;
typedef kernel_type::source_type source_type;
typedef kernel_type::target_type target_type;
typedef kernel_type::charge_type charge_type;
typedef kernel_type::result_type result_type;
// Init points and charges
std::vector<source_type> points(numBodies);
for (int k = 0; k < numBodies; ++k)
points[k] = source_type(drand(), drand(), drand());
//std::vector<point_type> target_points = points;
std::vector<charge_type> charges(numBodies);
for (int k = 0; k < numBodies; ++k) {
#if defined(STOKES_SPH)
#if defined(STRESSLET)
charges[k][0] = drand();
charges[k][1] = drand();
charges[k][2] = drand();
charges[k][3] = 1.;
charges[k][4] = 0.;
charges[k][5] = 0.;
#else
charges[k] = charge_type(1,1,1); // charge_type(drand(),drand(),drand());
#endif
#else
charges[k] = drand();
#endif
}
// Build the FMM
//fmm_plan plan = fmm_plan(K, bodies, opts);
FMM_plan<kernel_type> plan = FMM_plan<kernel_type>(K, points, opts);
// Execute the FMM
//fmm_execute(plan, charges, target_points);
std::vector<result_type> result = plan.execute(charges);
// Check the result
// TODO: More elegant
if (checkErrors) {
// choose a number of samples to use
int numSamples = std::min(numBodies, 1000);
std::vector<int> sample_map(numSamples);
std::vector<point_type> sample_targets(numSamples);
std::vector<result_type> exact(numSamples);
// sample the space (needs to be done better)
for (int i=0; i<numSamples; i++) {
int sample = i >> 15 % numBodies;
sample_map[i] = sample;
sample_targets[i] = points[sample];
}
// Compute the result with a direct matrix-vector multiplication
Direct::matvec(K, points.begin(), points.end(), charges.begin(),
sample_targets.begin(), sample_targets.end(), exact.begin());
#if defined(SPH_KERNEL) || defined(CART_KERNEL) || defined(YUKAWA_KERNEL)
result_type rdiff, rnorm;
for (unsigned k = 0; k < exact.size(); ++k) {
auto exact_val = exact[k];
auto fmm_val = result[sample_map[k]];
// printf("[%03d] exact: %lg, FMM: %lg\n", k, exact_val[0], fmm_val[0]);
rdiff += (fmm_val - exact_val) * (fmm_val - exact_val);
rnorm += exact_val * exact_val;
}
printf("Error (pot) : %.4e\n", sqrt(rdiff[0] / rnorm[0]));
printf("Error (acc) : %.4e\n", sqrt((rdiff[1]+rdiff[2]+rdiff[3]) /
(rnorm[1]+rnorm[2]+rnorm[3])));
#endif
#if defined(YUKAWA_SPH)
result_type rdiff = 0., rnorm = 0.;
for (unsigned k = 0; k < exact.size(); ++k) {
// printf("[%03d] exact: %lg, FMM: %lg\n", k, exact[k], result[k]);
auto exact_val = exact[k];
auto fmm_val = result[sample_map[k]];
rdiff = (fmm_val - exact_val) * (fmm_val - exact_val);
rnorm = exact_val * exact_val;
}
printf("Error (pot) : %.4e\n", sqrt(rdiff / rnorm));
#endif
#if defined(STOKES_SPH)
result_type rdiff = result_type(0.), rnorm = result_type(0.);
for (unsigned k = 0; k < exact.size(); ++k) {
auto exact_val = exact[k];
auto fmm_val = result[sample_map[k]];
// std::cout << exact_val << " : " << fmm_val << std::endl;
for (unsigned i=0; i < 3; i++) {
rdiff[i] += (fmm_val[i]-exact_val[i])*(fmm_val[i]-exact_val[i]);
rnorm[i] += exact_val[i]*exact_val[i];
}
}
auto div = rdiff/rnorm;
printf("Error (u) : %.4e, (v) : %.4e, (w) : %.4e\n",sqrt(div[0]),sqrt(div[1]),sqrt(div[2]));
#endif
#ifdef UNIT_KERNEL
int wrong_results = 0;
for (unsigned k = 0; k < exact.size(); ++k) {
auto exact_val = exact[k];
auto fmm_val = result[sample_map[k]];
// printf("[%03d] exact: %lg, FMM: %lg\n", k, exact[k], result[k]);
if ((exact_val - fmm_val) / exact_val > 1e-13)
++wrong_results;
}
printf("Wrong counts: %d\n", wrong_results);
#endif
}
}