VM2D 1.14
Vortex methods for 2D flows simulation
Loading...
Searching...
No Matches
knnCPU.h File Reference

knn CPU. More...

#include "BarnesHut.h"
Include dependency graph for knnCPU.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void WakekNNnewForCollaps (const std::vector< Vortex2D > &vtx, const size_t k, std::vector< std::vector< std::pair< double, size_t > > > &initdist, double cSP, double cRBP, double maxG, double epsCol, int type)
 
void WakekNNnewForEpsast (const std::vector< BH::PointsCopy > &vtx, const size_t k, std::vector< std::vector< std::pair< double, size_t > > > &initdist)
 

Detailed Description

knn CPU.

Author
\Version 1.14
Date
6 2026 .

Definition in file knnCPU.h.

Function Documentation

◆ WakekNNnewForCollaps()

void WakekNNnewForCollaps ( const std::vector< Vortex2D > &  vtx,
const size_t  k,
std::vector< std::vector< std::pair< double, size_t > > > &  initdist,
double  cSP,
double  cRBP,
double  maxG,
double  epsCol,
int  type 
)

Поиск границ габаритного прямоугольника (левый нижний и правый верхний)

Definition at line 307 of file knnCPU.cpp.

309{
310 using namespace knnNew;
311
312 double preTime = -omp_get_wtime();
313
314 const size_t n = vtx.size();
315
317 auto xx = std::minmax_element(vtx.begin(), vtx.end(), [](const Vortex2D& P1, const Vortex2D& P2) {return P1.r()[0] < P2.r()[0]; });
318 auto yy = std::minmax_element(vtx.begin(), vtx.end(), [](const Vortex2D& P1, const Vortex2D& P2) {return P1.r()[1] < P2.r()[1]; });
319
320 double scale = std::max(xx.second->r()[0] - xx.first->r()[0], yy.second->r()[1] - yy.first->r()[1]);
321
322 //сортировка массива (data) по мортоновским кодам
323 std::vector<unsigned int> s(256 * omp_get_max_threads());
324
325 std::vector<TParticleCode> mcdata(vtx.size());
326 std::vector<TParticleCode> mcdata_temp(vtx.size());
327
328 //std::vector<unsigned int> iq;
329
330 //Сдвигаем все точки
331 const int nSdvig = 5;
332 double tStart[nSdvig], tFinish[nSdvig];
333 double tm[nSdvig][5];
334
335 preTime += omp_get_wtime();
336
337 std::pair<double, size_t> zeroPair = std::make_pair<double, size_t>(0.0, 0);
338 std::pair<double, size_t> minusOnePair = std::make_pair<double, size_t>(-1.0, 0);
339
340 std::vector<std::pair<double, size_t>> dist(2 * k, { -1.0, 0 });
341 std::vector<size_t> loc(2 * k);
342 std::vector<size_t> counter(2 * k, 0);
343 std::vector<size_t> offset(2 * k, 0);
344 std::vector<size_t> counterScan(2 * k, 0);
345 std::vector<std::pair<double, size_t>> dstKeys1(2 * k, zeroPair);
346
347 std::vector<std::pair<double, size_t>> updateNN(k, zeroPair);
348 std::vector<std::pair<double, size_t>> dstKeys(k, zeroPair);
349
350 //14-05-2024
351 for (size_t sdvig = 0; sdvig < nSdvig /*5*/; ++sdvig)
352 {
353 tStart[sdvig] = omp_get_wtime();
354
355 const Point2D& lowLeft = { xx.first->r()[0], yy.first->r()[1] };
356 double* time = tm[sdvig];
357
358 //масштабирование координат вихрей в [0;0.75)^2, поиск их мортоновских кодов
359
360 time[0] = omp_get_wtime();
361#pragma omp parallel for
362 for (int i = 0; i < vtx.size(); ++i)
363 {
364 Point2D sh = (vtx[i].r() - lowLeft) * (0.75 / scale) + sdvig * Point2D{ 0.05, 0.05 };
365 mcdata[i].key = Morton2D(sh);
366 mcdata[i].originNumber = i;
367 }
368
369 time[1] = omp_get_wtime();
370
371 //сортировка единого массива (data и query) по мортоновским кодам
372 RSort_Parallel(mcdata.data(), mcdata_temp.data(), (int)mcdata.size(), s.data());
373
374 time[2] = omp_get_wtime();
375
376 for (size_t idx = 0; idx < 2 * k; ++idx)
377 {
378 dist[idx] = minusOnePair;
379 dstKeys1[idx] = zeroPair;
380 loc[idx] = counter[idx] = offset[idx] = counterScan[idx] = 0;
381 }
382
383 for (size_t idx = 0; idx < k; ++idx)
384 updateNN[idx] = dstKeys[idx] = zeroPair;
385
386 time[3] = omp_get_wtime();
387
388#pragma omp parallel for firstprivate(dist, loc, counter, offset, counterScan, updateNN, dstKeys, dstKeys1)
389 for (int i = 0; i < initdist.size(); ++i)
390 {
391 const Vortex2D& vtxi = vtx[mcdata[i].originNumber];
392
393 int cntr = 0;
394 int search = i - 1; // iq[i];
395 std::vector<std::pair<double, size_t>>& fillPosition = ((sdvig == 0) ? initdist[mcdata[i].originNumber] : dist);
396
397 while ((cntr < k) && (search >= 0))
398 {
399 const Vortex2D& vtxk = vtx[mcdata[search].originNumber];
400 bool flagExit, check;
401 double d2;
402 std::tie(flagExit, check) = calcCheck(vtxi, vtxk, maxG, cSP, cRBP, epsCol, type, d2);
403
404 if (flagExit)
405 break;
406
407 if ((mcdata[search].originNumber > mcdata[i].originNumber) && check)
408 fillPosition[cntr++] = { d2, mcdata[search].originNumber };
409
410 --search;
411 }
412
413 for (int w = cntr; w < k; ++w)
414 fillPosition[cntr++] = { 100000000.0, 0 };
415
416 search = i + 1;
417
418 while ((cntr < 2 * k) && (search < mcdata.size()))
419 {
420 const Vortex2D& vtxk = vtx[mcdata[search].originNumber];
421 bool flagExit, check;
422 double d2;
423 std::tie(flagExit, check) = calcCheck(vtxi, vtxk, maxG, cSP, cRBP, epsCol, type, d2);
424
425 if (flagExit)
426 break;
427
428 if ((mcdata[search].originNumber > mcdata[i].originNumber) && check)
429 fillPosition[cntr++] = { d2, mcdata[search].originNumber };
430
431 ++search;
432 }
433 for (int w = cntr; w < 2 * k; ++w)
434 fillPosition[cntr++] = { 100000000.0, 0 };
435
436 if (sdvig == 0)
437 {
438 newSort(initdist[mcdata[i].originNumber], dstKeys1);
439 initdist[mcdata[i].originNumber].resize(k);
440 }
441 else
442 {
443 newSort(dist, dstKeys1);
444 newMerge(mcdata[i].originNumber, initdist[mcdata[i].originNumber], dist, loc, counter, offset, counterScan, updateNN);
445 newSort(initdist[mcdata[i].originNumber], dstKeys);
446 }
447 }
448
449 time[4] = omp_get_wtime();
450
451 tFinish[sdvig] = omp_get_wtime();
452
453 }//for sdvig
454} // WakekNNnewForCollaps
Класс, опеделяющий двумерный вихревой элемент
Definition Vortex2D.h:59
R dist(const numvector< T, n > &x, const numvector< P, n > &y)
Вычисление расстояния между двумя точками
Definition numvector.h:851
void newMerge(int iii, std::vector< std::pair< double, size_t > > &currentNN, const std::vector< std::pair< double, size_t > > &candidateNN, std::vector< size_t > &loc, std::vector< size_t > &counter, std::vector< size_t > &offset, std::vector< size_t > &counterScan, std::vector< std::pair< double, size_t > > &updateNN)
Definition knnCPU.cpp:211
void RSort_Parallel(TParticleCode *m, TParticleCode *m_temp, unsigned int n, unsigned int *s)
Сортировка массива из мортоновский кодов
Definition knnCPU.cpp:95
unsigned int Morton2D(const Point2D &r)
Definition knnCPU.cpp:85
std::pair< bool, bool > calcCheck(const Vortex2D &vtxi, const Vortex2D &vtxk, double maxG, double cSP, double cRBP, double epsCol, int type, double &d2)
Definition knnCPU.cpp:263
void newSort(std::vector< std::pair< double, size_t > > &mass, std::vector< std::pair< double, size_t > > &dstKeys)
Definition knnCPU.cpp:189
Here is the caller graph for this function:

◆ WakekNNnewForEpsast()

void WakekNNnewForEpsast ( const std::vector< BH::PointsCopy > &  vtx,
const size_t  k,
std::vector< std::vector< std::pair< double, size_t > > > &  initdist 
)

Поиск границ габаритного прямоугольника (левый нижний и правый верхний)

Definition at line 458 of file knnCPU.cpp.

459{
460 using namespace knnNew;
461
462 double preTime = -omp_get_wtime();
463
464 const size_t n = vtx.size();
465
467 auto xx = std::minmax_element(vtx.begin(), vtx.end(), [](const Vortex2D& P1, const Vortex2D& P2) {return P1.r()[0] < P2.r()[0]; });
468 auto yy = std::minmax_element(vtx.begin(), vtx.end(), [](const Vortex2D& P1, const Vortex2D& P2) {return P1.r()[1] < P2.r()[1]; });
469
470 double scale = std::max(xx.second->r()[0] - xx.first->r()[0], yy.second->r()[1] - yy.first->r()[1]);
471
472 //сортировка массива (data) по мортоновским кодам
473 std::vector<unsigned int> s(256 * omp_get_max_threads());
474
475 std::vector<TParticleCode> mcdata(vtx.size());
476 std::vector<TParticleCode> mcdata_temp(vtx.size());
477
478 //std::vector<unsigned int> iq;
479
480 //Сдвигаем все точки
481 const int nSdvig = 5;
482 double tStart[nSdvig], tFinish[nSdvig];
483 double tm[nSdvig][5];
484
485 preTime += omp_get_wtime();
486
487 std::pair<double, size_t> zeroPair = std::make_pair<double, size_t>(0.0, 0);
488 std::pair<double, size_t> minusOnePair = std::make_pair<double, size_t>(-1.0, 0);
489
490 std::vector<std::pair<double, size_t>> dist(2 * k, { -1.0, 0 });
491 std::vector<size_t> loc(2 * k);
492 std::vector<size_t> counter(2 * k, 0);
493 std::vector<size_t> offset(2 * k, 0);
494 std::vector<size_t> counterScan(2 * k, 0);
495 std::vector<std::pair<double, size_t>> dstKeys1(2 * k, zeroPair);
496
497 std::vector<std::pair<double, size_t>> updateNN(k, zeroPair);
498 std::vector<std::pair<double, size_t>> dstKeys(k, zeroPair);
499
500 //14-05-2024
501 for (size_t sdvig = 0; sdvig < nSdvig /*5*/; ++sdvig)
502 {
503 tStart[sdvig] = omp_get_wtime();
504
505 const Point2D& lowLeft = { xx.first->r()[0], yy.first->r()[1] };
506 double* time = tm[sdvig];
507
508 //масштабирование координат вихрей в [0;0.75)^2, поиск их мортоновских кодов
509
510 time[0] = omp_get_wtime();
511#pragma omp parallel for
512 for (int i = 0; i < vtx.size(); ++i)
513 {
514 Point2D sh = (vtx[i].r() - lowLeft) * (0.75 / scale) + sdvig * Point2D{ 0.05, 0.05 };
515 mcdata[i].key = Morton2D(sh);
516 mcdata[i].originNumber = i;
517 }
518
519 time[1] = omp_get_wtime();
520
521 //сортировка единого массива (data и query) по мортоновским кодам
522 RSort_Parallel(mcdata.data(), mcdata_temp.data(), (int)mcdata.size(), s.data());
523
524 time[2] = omp_get_wtime();
525
526 for (size_t idx = 0; idx < 2 * k; ++idx)
527 {
528 dist[idx] = minusOnePair;
529 dstKeys1[idx] = zeroPair;
530 loc[idx] = counter[idx] = offset[idx] = counterScan[idx] = 0;
531 }
532
533 for (size_t idx = 0; idx < k; ++idx)
534 updateNN[idx] = dstKeys[idx] = zeroPair;
535
536 time[3] = omp_get_wtime();
537
538#pragma omp parallel for firstprivate(dist, loc, counter, offset, counterScan, updateNN, dstKeys, dstKeys1)
539 for (int i = 0; i < initdist.size(); ++i)
540 {
541 const Vortex2D& vtxi = vtx[mcdata[i].originNumber];
542
543 int cntr = 0;
544 int search = i - 1; // iq[i];
545 std::vector<std::pair<double, size_t>>& fillPosition = ((sdvig == 0) ? initdist[mcdata[i].originNumber] : dist);
546
547 while ((cntr < k) && (search >= 0))
548 {
549 const Vortex2D& vtxk = vtx[mcdata[search].originNumber];
550 double d2 = (vtxi.r()-vtxk.r()).length2();
551 fillPosition[cntr++] = { d2, mcdata[search].originNumber };
552 --search;
553 }
554
555 for (int w = cntr; w < k; ++w)
556 fillPosition[cntr++] = { 100000000.0, 0 };
557
558 search = i + 1;
559
560 while ((cntr < 2 * k) && (search < mcdata.size()))
561 {
562 const Vortex2D& vtxk = vtx[mcdata[search].originNumber];
563 double d2 = (vtxi.r() - vtxk.r()).length2();
564 fillPosition[cntr++] = { d2, mcdata[search].originNumber };
565 ++search;
566 }
567 for (int w = cntr; w < 2 * k; ++w)
568 fillPosition[cntr++] = { 100000000.0, 0 };
569
570 if (sdvig == 0)
571 {
572 newSort(initdist[mcdata[i].originNumber], dstKeys1);
573 initdist[mcdata[i].originNumber].resize(k);
574 }
575 else
576 {
577 newSort(dist, dstKeys1);
578 newMerge(mcdata[i].originNumber, initdist[mcdata[i].originNumber], dist, loc, counter, offset, counterScan, updateNN);
579 newSort(initdist[mcdata[i].originNumber], dstKeys);
580 }
581 }
582
583 time[4] = omp_get_wtime();
584
585 tFinish[sdvig] = omp_get_wtime();
586
587 }//for sdvig
588
589 //for (size_t sd = 0; sd < nSdvig; ++sd)
590 // std::cout << "knn[" << sd << "] = " << tFinish[sd] - tStart[sd] << "sec. " << std::endl;
591
592}
HD Point2D & r()
Функция для доступа к радиус-вектору вихря
Definition Vortex2D.h:87
Here is the call graph for this function: