309{
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
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
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
351 for (size_t sdvig = 0; sdvig < nSdvig ; ++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
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 };
366 mcdata[i].originNumber = i;
367 }
368
369 time[1] = omp_get_wtime();
370
371
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;
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 {
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 }
454}
Класс, опеделяющий двумерный вихревой элемент
R dist(const numvector< T, n > &x, const numvector< P, n > &y)
Вычисление расстояния между двумя точками
void newMerge(int iii, std::vector< std::pair< double, size_t > > ¤tNN, 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)
void RSort_Parallel(TParticleCode *m, TParticleCode *m_temp, unsigned int n, unsigned int *s)
Сортировка массива из мортоновский кодов
unsigned int Morton2D(const Point2D &r)
std::pair< bool, bool > calcCheck(const Vortex2D &vtxi, const Vortex2D &vtxk, double maxG, double cSP, double cRBP, double epsCol, int type, double &d2)
void newSort(std::vector< std::pair< double, size_t > > &mass, std::vector< std::pair< double, size_t > > &dstKeys)