PeriDEM 0.2.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
testNSearchLib.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2024 Prashant K. Jha
4 * -------------------------------------------
5 * PeriDEM https://github.com/prashjha/PeriDEM
6 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE)
9 */
10
11#include "testNSearchLib.h"
12#include "nsearch/nsearch.h"
13#include "util/function.h"
14#include "util/matrix.h"
15#include "util/methods.h"
16#include "util/point.h"
17#include "util/randomDist.h"
18#include "util/parallelUtil.h"
19#include <fmt/format.h>
20#include <bitset>
21#include <fstream>
22#include <iostream>
23#include <random>
24#include <vector>
25
26#include <taskflow/taskflow/taskflow.hpp>
27#include <taskflow/taskflow/algorithm/for_each.hpp>
28
29namespace {
30
31bool isInList(const std::vector<size_t> *list, size_t i) {
32 for (auto j : *list)
33 if (j == i)
34 return true;
35
36 return false;
37}
38
39void stats(const std::vector<double> &x, double &mean, double &std) {
40 double mu = 0.;
41 for (auto &y : x)
42 mu += y;
43 mu = mu / x.size();
44
45 double s = 0.;
46 for (auto &y : x)
47 s += (y - mu) * (y - mu);
48 s = s / x.size();
49
50 std = std::sqrt(s);
51 mean = mu;
52}
53
54void lattice(double L, size_t Nx, size_t Ny, size_t Nz, double dL, int seed,
55 std::vector<util::Point> &x, int dim = 3) {
56
58 UniformDistribution dist(-dL, dL);
59
60 if (dim == 2)
61 x.resize(Nx * Ny);
62 else if (dim == 3)
63 x.resize(Nx * Ny * Nz);
64 else {
65 std::cerr << "Dimension = " << dim << " not supprted.\n";
66 exit(EXIT_FAILURE);
67 }
68
69 size_t count = 0;
70 for (size_t i = 0; i < Nx; i++) {
71 for (size_t j = 0; j < Ny; j++) {
72 if (dim == 2) {
73 auto y = util::Point();
74 y.d_x = i * L + dist(gen);
75 y.d_y = j * L + dist(gen);
76 y.d_z = 0.;
77
78 x[count] = y;
79 count++;
80 } else if (dim == 3) {
81 for (size_t k = 0; k < Nz; k++) {
82 auto y = util::Point();
83 y.d_x = i * L + dist(gen);
84 y.d_y = j * L + dist(gen);
85 y.d_z = k * L + dist(gen);
86
87 x[count] = y;
88 count++;
89 } // loop over k
90 } // if-else
91 } // loop over j
92 } // loop over i
93}
94
95void assignRandomTags(std::vector<util::Point> &x,
96 int numTags,
97 int seed,
98 std::vector<size_t> &xTags) {
100 UniformIntDistribution dist(0, numTags - 1);
101
102 for (size_t i=0; i<x.size(); i++)
103 xTags[i] = dist(gen);
104}
105
106template <class NSearch>
107double neighSearchTree(const std::vector<util::Point> &x,
108 const std::unique_ptr<NSearch> &nsearch,
109 const double &r,
110 std::vector<std::vector<size_t>> &neigh,
111 std::vector<std::vector<float>> &neigh_sq_dist) {
112 neigh.resize(x.size());
113 neigh_sq_dist.resize(x.size());
114 auto t1 = steady_clock::now();
115
116 tf::Executor executor(util::parallel::getNThreads());
117 tf::Taskflow taskflow;
118
119 taskflow.for_each_index((std::size_t) 0, x.size(), (std::size_t) 1, [&x, &neigh, &neigh_sq_dist, &nsearch, r](std::size_t i) {
120 std::vector<int> neighs;
121 std::vector<float> sqr_dist;
122
123 if (nsearch->radiusSearch(x[i], r, neighs, sqr_dist) >
124 0) {
125 for (std::size_t j = 0; j < neighs.size(); ++j)
126 if (size_t(neighs[j]) != i) {
127 neigh[i].push_back(size_t(neighs[j]));
128 neigh_sq_dist[i].push_back(sqr_dist[j]);
129 }
130 }
131 }
132 ); // for_each
133
134 executor.run(taskflow).get();
135
136 auto t2 = steady_clock::now();
137 return util::methods::timeDiff(t1, t2, "microseconds");
138}
139
140template <class NSearch>
141double neighSearchTreeSizet(const std::vector<util::Point> &x,
142 const std::unique_ptr<NSearch> &nsearch,
143 const double &r,
144 std::vector<std::vector<size_t>> &neigh,
145 std::vector<std::vector<float>> &neigh_sq_dist) {
146 neigh.resize(x.size());
147 neigh_sq_dist.resize(x.size());
148 auto t1 = steady_clock::now();
149
150 tf::Executor executor(util::parallel::getNThreads());
151 tf::Taskflow taskflow;
152
153 taskflow.for_each_index((std::size_t) 0, x.size(), (std::size_t) 1, [&x, &neigh, &neigh_sq_dist, &nsearch, r](std::size_t i) {
154 std::vector<size_t> neighs;
155 std::vector<double> sqr_dist;
156
157 if (nsearch->radiusSearch(x[i], r, neighs, sqr_dist) >
158 0) {
159 for (std::size_t j = 0; j < neighs.size(); ++j)
160 if (size_t(neighs[j]) != i) {
161 neigh[i].push_back(size_t(neighs[j]));
162 neigh_sq_dist[i].push_back(sqr_dist[j]);
163 }
164 }
165 }
166 ); // for_each
167
168 executor.run(taskflow).get();
169
170 auto t2 = steady_clock::now();
171 return util::methods::timeDiff(t1, t2, "microseconds");
172}
173
174template <class NSearch>
175double neighSearchTreeSizetExcludeInclude(const std::vector<util::Point> &x,
176 const std::vector<size_t> &xTags,
177 const std::unique_ptr<NSearch> &nsearch,
178 const double &r,
179 std::vector<std::vector<size_t>> &neigh,
180 std::vector<std::vector<float>> &neigh_sq_dist,
181 int selection_criteria) {
182
183 // selection_criteria = 1 --> exclude search
184 // selection_criteria = 2 --> include search
185
186 neigh.resize(x.size());
187 neigh_sq_dist.resize(x.size());
188 auto t1 = steady_clock::now();
189
190 tf::Executor executor(util::parallel::getNThreads());
191 tf::Taskflow taskflow;
192
193 taskflow.for_each_index((std::size_t) 0,
194 x.size(),
195 (std::size_t) 1,
196 [&x,
197 &xTags,
198 &neigh,
199 &neigh_sq_dist,
200 &nsearch,
201 r,
202 selection_criteria](std::size_t i) {
203
204 std::vector<size_t> neighs;
205 std::vector<double> sqr_dist;
206 size_t n = 0;
207
208 if (selection_criteria == 1)
209 n = nsearch->radiusSearchExcludeTag(x[i], r,
210 neighs,
211 sqr_dist,
212 xTags[i],
213 xTags);
214 else if (selection_criteria == 2)
215 n = nsearch->radiusSearchIncludeTag(x[i], r,
216 neighs,
217 sqr_dist,
218 xTags[i],
219 xTags);
220 if (n > 0) {
221 for (std::size_t j = 0; j < neighs.size(); ++j)
222 if (size_t(neighs[j]) != i) {
223 neigh[i].push_back(size_t(neighs[j]));
224 neigh_sq_dist[i].push_back(sqr_dist[j]);
225 }
226 }
227 }
228 ); // for_each
229
230 executor.run(taskflow).get();
231
232 auto t2 = steady_clock::now();
233 return util::methods::timeDiff(t1, t2, "microseconds");
234}
235
236double neighSearchBrute(const std::vector<util::Point> &x, const double &r,
237 std::vector<std::vector<size_t>> &neigh,
238 std::vector<std::vector<float>> &neigh_sq_dist) {
239
240 neigh.resize(x.size());
241 neigh_sq_dist.resize(x.size());
242
243 auto t1 = steady_clock::now();
244
245 tf::Executor executor(util::parallel::getNThreads());
246 tf::Taskflow taskflow;
247
248 taskflow.for_each_index((std::size_t) 0,
249 x.size(),
250 (std::size_t) 1,
251 [&x,
252 &neigh,
253 &neigh_sq_dist,
254 r](std::size_t i) {
255 auto searchPoint = x[i];
256
257 for (size_t j = 0; j < x.size(); j++) {
258 auto dx = searchPoint - x[j];
259 auto l = dx.length();
260 if (util::isLess(l, r) and j != i) {
261 neigh[i].push_back(j);
262 neigh_sq_dist[i].push_back(l);
263 }
264 }
265 }
266 ); // for_each
267
268 executor.run(taskflow).get();
269
270 auto t2 = steady_clock::now();
271 return util::methods::timeDiff(t1, t2, "microseconds");
272}
273
274
275double neighSearchBruteExcludeInclude(const std::vector<util::Point> &x,
276 const std::vector<size_t> &xTags,
277 const double &r,
278 std::vector<std::vector<size_t>> &neigh,
279 std::vector<std::vector<float>> &neigh_sq_dist,
280 int selection_criteria) {
281
282 // selection_criteria = 1 --> exclude search
283 // selection_criteria = 2 --> include search
284
285 neigh.resize(x.size());
286 neigh_sq_dist.resize(x.size());
287
288 auto t1 = steady_clock::now();
289
290 tf::Executor executor(util::parallel::getNThreads());
291 tf::Taskflow taskflow;
292
293 taskflow.for_each_index((std::size_t) 0,
294 x.size(),
295 (std::size_t) 1,
296 [&x,
297 &xTags,
298 &neigh,
299 &neigh_sq_dist,
300 r,
301 selection_criteria](std::size_t i) {
302
303 auto searchPoint = x[i];
304 auto searchPointTag = xTags[i];
305
306 for (size_t j = 0; j < x.size(); j++) {
307 auto dx = searchPoint - x[j];
308 auto l = dx.length();
309 if (util::isLess(l, r) and j != i) {
310
311 if (selection_criteria == 1) {
312 if (xTags[j] != searchPointTag) {
313 neigh[i].push_back(j);
314 neigh_sq_dist[i].push_back(l);
315 }
316 }
317 else if (selection_criteria == 2) {
318 if (xTags[j] == searchPointTag) {
319 neigh[i].push_back(j);
320 neigh_sq_dist[i].push_back(l);
321 }
322 }
323 }
324 }
325 }
326 ); // for_each
327
328 executor.run(taskflow).get();
329
330 auto t2 = steady_clock::now();
331 return util::methods::timeDiff(t1, t2, "microseconds");
332}
333
334
335template <class NSearch>
336double neighSearchTreeClosestPointSizet(const std::vector<util::Point> &x,
337 const std::unique_ptr<NSearch> &nsearch,
338 const int &seed,
339 const double &L,
340 const double &dL,
341 std::vector<util::Point> &search_points,
342 std::vector<size_t> &err_points,
343 std::vector<double> &err_dist) {
344
345 search_points.resize(x.size());
346 err_points.resize(x.size());
347 err_dist.resize(x.size());
348
349 // set perturbation length much smaller than the dL
350 double dx_perturb = dL/100;
351
352 // random number generator
354 UniformDistribution dist(-dx_perturb, dx_perturb);
355
356 for (size_t i=0; i<x.size(); i++) {
357 const auto &xi = x[i];
358
359 // get a query point that is close to xi
360 auto xi_perturb = xi;
361 for (size_t k=0; k<3; k++)
362 xi_perturb[k] += dist(gen);
363
364 search_points[i] = xi_perturb;
365 }
366
367 auto t1 = steady_clock::now();
368
369 tf::Executor executor(util::parallel::getNThreads());
370 tf::Taskflow taskflow;
371
372 taskflow.for_each_index((std::size_t) 0, x.size(), (std::size_t) 1, [&x,
373 &search_points,
374 &err_points, &err_dist, &nsearch](std::size_t i) {
375
376 const auto &xi = x[i];
377
378 // get a query point that is close to xi
379 const auto &xi_perturb = search_points[i];
380
381 // set true values
382 size_t true_neigh = i;
383 double true_dist = (xi - xi_perturb).length();
384
385 size_t found_neigh;
386 double found_dist = 0.;
387
388 // find closest neighbor using nsearch
389 nsearch->closestPoint(xi_perturb, found_neigh, found_dist);
390
391 if (true_neigh != found_neigh) {
392 err_points[i] = found_neigh;
393 err_dist[i] = true_dist - found_dist;
394 }
395 else {
396 err_points[i] = -1;
397 err_dist[i] = 0.;
398 }
399 }
400 ); // for_each
401
402 executor.run(taskflow).get();
403
404 auto t2 = steady_clock::now();
405 return util::methods::timeDiff(t1, t2, "microseconds");
406}
407
408std::string compare_results(const std::vector<std::vector<size_t>> &neigh1,
409 const std::vector<std::vector<size_t>> &neigh2,
410 std::vector<std::string> tags,
411 int check_nodes_num = -1,
412 bool only_err_count = false) {
413 size_t error_size = 0;
414 size_t error_nodes = 0;
415 size_t error_neighs = 0;
416 std::ostringstream composs;
417 for (size_t i = 0; i < neigh1.size(); i++) {
418
419 if (check_nodes_num > 0 and i > check_nodes_num)
420 continue;
421
422 size_t err_neighs = 0;
423 auto &n1 = neigh1[i];
424 auto &n2 = neigh2[i];
425
426 bool header_done = false;
427 if (n1.size() != n2.size()) {
428 composs << " Node = " << i << " \n";
429 composs << fmt::format(" size ({}) {} != {} ({}) not matching\n",
430 tags[0], n1.size(), n2.size(), tags[1]);
431 header_done = true;
432 error_size++;
433 }
434
435 for (auto j : n2) {
436 if (!isInList(&n1, j)) {
437 if (!header_done)
438 composs << " Node = " << i << " \n";
439
440 composs << fmt::format(" neigh = {} in {} search not found in {} "
441 "search neighs list\n",
442 j, tags[1], tags[0]);
443 err_neighs += 1;
444 }
445 }
446
447 if (err_neighs > 0)
448 error_neighs += err_neighs;
449 }
450
451 if (only_err_count)
452 return fmt::format(" error_size = {}, error_neighs = {}\n", error_size,
453 error_neighs);
454 else
455 return fmt::format(" error_size = {}, error_neighs = {}\n", error_size,
456 error_neighs) +
457 composs.str();
458}
459
461 const std::vector<util::Point> &x,
462 const std::vector<util::Point> &search_points,
463 const std::vector<size_t> &err_points,
464 const std::vector<double> &err_dist,
465 bool only_err_count = false) {
466
467 size_t error_size = 0;
468 std::ostringstream composs;
469
470 for (size_t i = 0; i < err_points.size(); i++) {
471
472 if (err_points[i] != -1) {
473 composs << fmt::format(" Node = {} at location = {}, "
474 "Search point = {}, closest point id = {} at"
475 " location = {}. True dist = {}, found "
476 "dist = {}\n",
477 i, x[i].printStr(), search_points[i]
478 .printStr(), err_points[i], x[err_points[i]]
479 .printStr(), (x[i] - search_points[i])
480 .length(), err_dist[i]);
481 error_size++;
482 }
483 }
484
485 if (only_err_count)
486 return fmt::format(" error_size = {}\n", error_size);
487 else
488 return fmt::format(" error_size = {}\n", error_size) +
489 composs.str();
490 }
491} // namespace
492
493template <int dim>
494std::string test::testNanoflann(size_t N, double L, double dL, int seed) {
495
496 if (dim < 2 or dim > 3) {
497 return "testNanoflann: only dim = 2, 3 are accepted.\n";
498 }
499
500 // create 3D lattice and perturb each lattice point
501 size_t Nx, Ny, Nz;
502 Nx = Ny = Nz = N;
503 size_t N_tot = Nx * Ny;
504 if (dim == 3)
505 N_tot = N_tot * Nz;
506
507 std::vector<util::Point> x(N_tot, util::Point());
508 lattice(L, Nx, Ny, Nz, dL, seed, x, dim);
509 std::cout << "Total points = " << x.size() << "\n";
510
511
512 if (dim == 2) {
513 std::vector<std::vector<size_t>> neigh_nflann(N_tot, std::vector<size_t>());
514 std::vector<std::vector<float>> neigh_nflann_sq_dist(N_tot,
515 std::vector<float>());
516
517 std::vector<std::vector<size_t>> neigh_nflann_3d(N_tot, std::vector<size_t>());
518 std::vector<std::vector<float>> neigh_nflann_3d_sq_dist(N_tot,
519 std::vector<float>());
520
521 std::vector<std::vector<size_t>> neigh_brute(N_tot, std::vector<size_t>());
522 std::vector<std::vector<float>> neigh_brute_sq_dist(N_tot,
523 std::vector<float>());
524
525 // brute-force search
526 double search_r = 1.5 * L;
527 auto brute_force_search_time =
528 neighSearchBrute(x, search_r, neigh_brute, neigh_brute_sq_dist);
529
530 // nanoflann tree search
531 std::unique_ptr<nsearch::NFlannSearchKd<3>> nflann_nsearch_3d
532 = std::make_unique<nsearch::NFlannSearchKd<3>>(x, 0);
533
534 std::unique_ptr<nsearch::NFlannSearchKd<dim>> nflann_nsearch
535 = std::make_unique<nsearch::NFlannSearchKd<dim>>(x, 0);
536
537 auto nflann_tree_set_time_3d = nflann_nsearch_3d->setInputCloud();
538 auto nflann_tree_search_time_3d =
539 neighSearchTreeSizet(x, nflann_nsearch_3d, search_r, neigh_nflann_3d, neigh_nflann_3d_sq_dist);
540
541 auto nflann_tree_set_time = nflann_nsearch->setInputCloud();
542 auto nflann_tree_search_time =
543 neighSearchTreeSizet(x, nflann_nsearch, search_r, neigh_nflann, neigh_nflann_sq_dist);
544
545 // Compare search results
546 auto nflann_brute_compare = compare_results(
547 neigh_nflann, neigh_brute, {"nflann_tree", "brute_force"}, -1, true);
548
549 auto nflann_brute_compare_3d = compare_results(
550 neigh_nflann_3d, neigh_brute, {"nflann_tree-3d", "brute_force"}, -1, true);
551
552 std::ostringstream msg;
553 msg << fmt::format(" Setup times (microseconds): \n"
554 " nflann_tree_set_time = {} \n "
555 " nflann_tree_set_time_3d = {}\n",
556 nflann_tree_set_time, nflann_tree_set_time_3d);
557
558 msg << fmt::format(" Search times (microseconds): \n"
559 " brute_force_search_time = {}\n"
560 " nflann_tree_search_time = {}\n"
561 " nflann_tree_search_time_3d = {}\n",
562 brute_force_search_time,
563 nflann_tree_search_time,
564 nflann_tree_search_time_3d);
565
566 msg << fmt::format(" Comparison results: \n"
567 " nflann_brute_compare: \n{}\n",
568 nflann_brute_compare);
569
570 msg << fmt::format(" Comparison results: \n"
571 " nflann_brute_compare_3d: \n{}\n",
572 nflann_brute_compare_3d);
573
574 return msg.str();
575 }
576 else if (dim == 3) {
577 std::vector<std::vector<size_t>> neigh_nflann(N_tot, std::vector<size_t>());
578 std::vector<std::vector<float>> neigh_nflann_sq_dist(N_tot,
579 std::vector<float>());
580
581 std::vector<std::vector<size_t>> neigh_brute(N_tot, std::vector<size_t>());
582 std::vector<std::vector<float>> neigh_brute_sq_dist(N_tot,
583 std::vector<float>());
584
585 // brute-force search
586 double search_r = 1.5 * L;
587 auto brute_force_search_time =
588 neighSearchBrute(x, search_r, neigh_brute, neigh_brute_sq_dist);
589
590 // nanoflann tree search
591 std::unique_ptr<nsearch::NFlannSearchKd<dim>> nflann_nsearch
592 = std::make_unique<nsearch::NFlannSearchKd<dim>>(x, 0);
593
594 auto nflann_tree_set_time = nflann_nsearch->setInputCloud();
595 auto nflann_tree_search_time =
596 neighSearchTreeSizet(x, nflann_nsearch, search_r, neigh_nflann, neigh_nflann_sq_dist);
597
598 // Compare search results
599 auto nflann_brute_compare = compare_results(
600 neigh_nflann, neigh_brute, {"nflann_tree", "brute_force"}, -1, true);
601
602 std::ostringstream msg;
603 msg << fmt::format(" Setup times (microseconds): \n"
604 " nflann_tree_set_time = {}\n",
605 nflann_tree_set_time);
606
607 msg << fmt::format(" Search times (microseconds): \n"
608 " brute_force_search_time = {}\n"
609 " nflann_tree_search_time = {}\n",
610 brute_force_search_time,
611 nflann_tree_search_time);
612
613 msg << fmt::format(" Comparison results: \n"
614 " nflann_brute_compare: \n{}\n",
615 nflann_brute_compare);
616
617 return msg.str();
618 }
619
620
621}
622
623
624template <int dim>
625std::string test::testNanoflannExcludeInclude(size_t N, double L,
626 double dL, int seed, testNSearchData &data) {
627
628 if (dim < 2 or dim > 3) {
629 return "testNanoflannExcludeInclude: only dim = 2, 3 are accepted.\n";
630 }
631
632 // create 3D lattice and perturb each lattice point
633 size_t Nx, Ny, Nz;
634 Nx = Ny = Nz = N;
635 size_t N_tot = Nx * Ny;
636 if (dim == 3)
637 N_tot = N_tot * Nz;
638
639 std::vector<util::Point> x(N_tot, util::Point());
640 std::vector<size_t> xTags(N_tot, 0);
641 lattice(L, Nx, Ny, Nz, dL, seed, x, dim);
642 assignRandomTags(x, data.d_numTags, seed, xTags);
643 data.d_numPoints = x.size();
644 std::cout << "Total points = " << x.size() << "\n";
645
646 std::vector<std::vector<size_t>> neigh_default_nflann(N_tot, std::vector<size_t>());
647 std::vector<std::vector<float>> neigh_default_nflann_sq_dist(N_tot,
648 std::vector<float>());
649
650 std::vector<std::vector<size_t>> neigh_exclude_nflann(N_tot, std::vector<size_t>());
651 std::vector<std::vector<float>> neigh_exclude_nflann_sq_dist(N_tot,
652 std::vector<float>());
653
654 std::vector<std::vector<size_t>> neigh_include_nflann(N_tot, std::vector<size_t>());
655 std::vector<std::vector<float>> neigh_include_nflann_sq_dist(N_tot,
656 std::vector<float>());
657
658
659 std::vector<std::vector<size_t>> neigh_default_brute(N_tot, std::vector<size_t>());
660 std::vector<std::vector<float>> neigh_default_brute_sq_dist(N_tot,
661 std::vector<float>());
662
663 std::vector<std::vector<size_t>> neigh_exclude_brute(N_tot, std::vector<size_t>());
664 std::vector<std::vector<float>> neigh_exclude_brute_sq_dist(N_tot,
665 std::vector<float>());
666
667 std::vector<std::vector<size_t>> neigh_include_brute(N_tot, std::vector<size_t>());
668 std::vector<std::vector<float>> neigh_include_brute_sq_dist(N_tot,
669 std::vector<float>());
670
671 // brute-force search
672 double search_r = 3. * L;
673
676 search_r,
677 neigh_default_brute,
678 neigh_default_brute_sq_dist);
679
681 neighSearchBruteExcludeInclude(x, xTags, search_r,
682 neigh_exclude_brute,
683 neigh_exclude_brute_sq_dist,
684 1);
685
687 neighSearchBruteExcludeInclude(x, xTags, search_r,
688 neigh_include_brute,
689 neigh_include_brute_sq_dist,
690 2);
691
692 // nanoflann tree search
693 std::unique_ptr<nsearch::NFlannSearchKd<dim>> nflann_nsearch
694 = std::make_unique<nsearch::NFlannSearchKd<dim>>(x, 0,
695 data.d_leafMaxSize);
696
697 data.d_treeBuildTime = nflann_nsearch->setInputCloud();
698
699 // default
701 neighSearchTreeSizet(x, nflann_nsearch,
702 search_r, neigh_default_nflann,
703 neigh_default_nflann_sq_dist);
704
705 // exclude
707 neighSearchTreeSizetExcludeInclude(x, xTags, nflann_nsearch,
708 search_r, neigh_exclude_nflann,
709 neigh_exclude_nflann_sq_dist,
710 1);
711
712 // include
714 neighSearchTreeSizetExcludeInclude(x, xTags, nflann_nsearch,
715 search_r, neigh_include_nflann,
716 neigh_include_nflann_sq_dist,
717 2);
718
719 // Compare search results
720 auto nflann_brute_compare_default = compare_results(
721 neigh_default_nflann, neigh_default_brute,
722 {"nflann_tree_default", "brute_force_default"}, -1, true);
723
724 auto nflann_brute_compare_exclude = compare_results(
725 neigh_exclude_nflann, neigh_exclude_brute,
726 {"nflann_tree_exclude", "brute_force_exclude"}, -1, true);
727
728 auto nflann_brute_compare_include = compare_results(
729 neigh_include_nflann, neigh_include_brute,
730 {"nflann_tree_include", "brute_force_include"}, -1, true);
731
732 std::ostringstream msg;
733 msg << fmt::format(" Setup times (microseconds): \n"
734 " nflann_tree_set_time = {}\n",
735 data.d_treeBuildTime);
736
737 msg << fmt::format(" Default search times (microseconds): \n"
738 " brute_force_search_time = {}\n"
739 " nflann_tree_search_time = {}\n",
742
743 msg << fmt::format(" Exclude comparison results: \n"
744 " nflann_brute_compare: \n{}\n",
745 nflann_brute_compare_default);
746
747 msg << fmt::format(" Exclude search times (microseconds): \n"
748 " brute_force_search_time = {}\n"
749 " nflann_tree_search_time = {}\n",
752
753 msg << fmt::format(" Exclude comparison results: \n"
754 " nflann_brute_compare: \n{}\n",
755 nflann_brute_compare_exclude);
756
757 msg << fmt::format(" Include search times (microseconds): \n"
758 " brute_force_search_time = {}\n"
759 " nflann_tree_search_time = {}\n",
762
763 msg << fmt::format(" Include comparison results: \n"
764 " nflann_brute_compare: \n{}\n",
765 nflann_brute_compare_include);
766
767
768 msg << fmt::format(" Nflann all search times (microseconds): \n"
769 " default = {}\n"
770 " exclude = {}\n"
771 " include = {}\n",
775
776 return msg.str();
777
778
779}
780
781std::string test::testNanoflannClosestPoint(size_t N, double L, double dL, int seed) {
782
783 // create 3D lattice and perturb each lattice point
784 size_t Nx, Ny, Nz;
785 Nx = Ny = Nz = N;
786 size_t N_tot = Nx * Ny * Nz;
787
788 std::vector<util::Point> x(N_tot, util::Point());
789 lattice(L, Nx, Ny, Nz, dL, seed, x, 3);
790 std::cout << "Total points = " << x.size() << "\n";
791
792 // nanoflann tree search
793 auto nflann_nsearch
794 = std::make_unique<nsearch::NFlannSearchKd<3>>(x, 0);
795
796 auto nflann_tree_set_time = nflann_nsearch->setInputCloud();
797
798 std::vector<size_t> err_points;
799 std::vector<util::Point> search_points;
800 std::vector<double> err_dist;
801 auto nsearch_search_time = neighSearchTreeClosestPointSizet(
802 x, nflann_nsearch, seed, L, dL, search_points, err_points, err_dist);
803
804 // Compare search results
805 auto nflann_compare = compare_closest_point_results(x,
806 search_points,
807 err_points,
808 err_dist, false);
809
810 std::ostringstream msg;
811 msg << fmt::format(" Setup times (microseconds): \n"
812 " nflann_tree_set_time = {}\n",
813 nflann_tree_set_time);
814
815 msg << fmt::format(" Comparison results: \n"
816 " nflann_compare: \n{}\n",
817 nflann_compare);
818
819 return msg.str();
820
821
822
823}
824
825
826template std::string test::testNanoflann<2>(size_t N, double L, double dL, int seed);
827template std::string test::testNanoflann<3>(size_t N, double L, double dL, int seed);
828
829template std::string test::testNanoflannExcludeInclude<2>(size_t N, double L,
830 double dL, int seed, testNSearchData &data);
831template std::string test::testNanoflannExcludeInclude<3>(size_t N, double L,
832 double dL, int seed, testNSearchData &data);
double neighSearchTreeClosestPointSizet(const std::vector< util::Point > &x, const std::unique_ptr< NSearch > &nsearch, const int &seed, const double &L, const double &dL, std::vector< util::Point > &search_points, std::vector< size_t > &err_points, std::vector< double > &err_dist)
double neighSearchTreeSizet(const std::vector< util::Point > &x, const std::unique_ptr< NSearch > &nsearch, const double &r, std::vector< std::vector< size_t > > &neigh, std::vector< std::vector< float > > &neigh_sq_dist)
double neighSearchTree(const std::vector< util::Point > &x, const std::unique_ptr< NSearch > &nsearch, const double &r, std::vector< std::vector< size_t > > &neigh, std::vector< std::vector< float > > &neigh_sq_dist)
std::string compare_closest_point_results(const std::vector< util::Point > &x, const std::vector< util::Point > &search_points, const std::vector< size_t > &err_points, const std::vector< double > &err_dist, bool only_err_count=false)
void assignRandomTags(std::vector< util::Point > &x, int numTags, int seed, std::vector< size_t > &xTags)
void lattice(double L, size_t Nx, size_t Ny, size_t Nz, double dL, int seed, std::vector< util::Point > &x, int dim=3)
void stats(const std::vector< double > &x, double &mean, double &std)
bool isInList(const std::vector< size_t > *list, size_t i)
double neighSearchBruteExcludeInclude(const std::vector< util::Point > &x, const std::vector< size_t > &xTags, const double &r, std::vector< std::vector< size_t > > &neigh, std::vector< std::vector< float > > &neigh_sq_dist, int selection_criteria)
std::string compare_results(const std::vector< std::vector< size_t > > &neigh1, const std::vector< std::vector< size_t > > &neigh2, std::vector< std::string > tags, int check_nodes_num=-1, bool only_err_count=false)
double neighSearchBrute(const std::vector< util::Point > &x, const double &r, std::vector< std::vector< size_t > > &neigh, std::vector< std::vector< float > > &neigh_sq_dist)
double neighSearchTreeSizetExcludeInclude(const std::vector< util::Point > &x, const std::vector< size_t > &xTags, const std::unique_ptr< NSearch > &nsearch, const double &r, std::vector< std::vector< size_t > > &neigh, std::vector< std::vector< float > > &neigh_sq_dist, int selection_criteria)
Methods for performing efficient search of neighboring points.
Definition nflannSetup.h:17
std::string testNanoflannExcludeInclude(size_t N, double L, double dL, int seed, testNSearchData &data)
Perform test on nsearch.
std::string testNanoflannClosestPoint(size_t N, double L, double dL, int seed)
Perform test on nsearch.
std::string testNanoflann(size_t N, double L, double dL, int seed)
Perform test on nsearch.
float timeDiff(std::chrono::steady_clock::time_point begin, std::chrono::steady_clock::time_point end, std::string unit="microseconds")
Returns difference between two times.
Definition methods.h:304
unsigned int getNThreads()
Get number of threads to be used by taskflow.
RandGenerator get_rd_gen(int seed=-1)
Return random number generator.
Definition randomDist.h:30
std::uniform_real_distribution UniformDistribution
Definition randomDist.h:18
std::mt19937 RandGenerator
Definition randomDist.h:16
std::uniform_int_distribution UniformIntDistribution
Definition randomDist.h:20
A structure to represent 3d vectors.
Definition point.h:30