1#include "VirtualSpatiallyAdaptiveStrategy.h"
3#include "ParticleSystem/Module/SummationDensity.h"
4#include "Topology/GridHash.h"
6#include <thrust/sort.h>
11 __constant__ int diff_v[27][3] =
43 __constant__ int diff_v_33[33][3] =
82 __constant__ int diff_v_125[125][3] =
212 IMPLEMENT_TCLASS(VirtualSpatiallyAdaptiveStrategy, TDataType)
214 template<typename TDataType>
215 VirtualSpatiallyAdaptiveStrategy<TDataType>::VirtualSpatiallyAdaptiveStrategy()
216 : VirtualParticleGenerator<TDataType>()
219 this->varSamplingDistance()->setValue(Real(0.005));
220 this->varRestDensity()->setValue(Real(1000));
221 gridSize = this->varSamplingDistance()->getData();
226 template<typename TDataType>
227 VirtualSpatiallyAdaptiveStrategy<TDataType>::~VirtualSpatiallyAdaptiveStrategy()
232 template<typename Real, typename Coord>
233 __global__ void AFV_VirtualPositionCompute(
243 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
244 if (pId >= vpos.size()) return;
247 vpos[pId][1] = loPoint[1] + Real(pId / (nx * nz)) * ds;
248 vpos[pId][0] = loPoint[0] + Real(pId % nx) * ds;
249 vpos[pId][2] = loPoint[2] + Real(pId % (nx * nz) / nx) * ds;
253 *@brief Virtual particles' candinate points
254 * Every particle has 8 neighbors.
256 template<typename Real, typename Coord>
257 __global__ void AFV_AnchorNeighbor_8
259 DArray<Coord> anchorPoint,
265 int id = threadIdx.x + (blockIdx.x * blockDim.x);
266 if (id >= pos.size()) return;
270 Coord pos_ref = pos[id] - origin + Coord (dh/4.0);
271 //Coord pos_ref = pos[id] - origin;
274 a[0] = (Real)((int)(floor(pos_ref[0] / dh))) * dh;
275 a[1] = (Real)((int)(floor(pos_ref[1] / dh))) * dh;
276 a[2] = (Real)((int)(floor(pos_ref[2] / dh))) * dh;
278 anchorPoint[id * 8] = Coord(a[0], a[1], a[2]);
279 anchorPoint[id * 8 + 1] = Coord(a[0] + dh, a[1], a[2]);
280 anchorPoint[id * 8 + 2] = Coord(a[0] + dh, a[1] + dh, a[2]);
281 anchorPoint[id * 8 + 3] = Coord(a[0] + dh, a[1] + dh, a[2] + dh);
282 anchorPoint[id * 8 + 4] = Coord(a[0], a[1] + dh, a[2]);
283 anchorPoint[id * 8 + 5] = Coord(a[0], a[1] + dh, a[2] + dh);
284 anchorPoint[id * 8 + 6] = Coord(a[0], a[1], a[2] + dh);
285 anchorPoint[id * 8 + 7] = Coord(a[0] + dh, a[1], a[2] + dh);
291 *@brief Virtual particles' candinate points
292 * Every particle has 27 neighbors.
294 template<typename Real, typename Coord>
295 __global__ void AFV_AnchorNeighbor_27
297 DArray<Coord> anchorPoint,
303 int id = threadIdx.x + (blockIdx.x * blockDim.x);
304 if (id >= pos.size()) return;
306 Coord pos_ref = pos[id] - origin + dh/2;
309 a[0] = (Real)((int)(floor(pos_ref[0] / dh))) * dh;
310 a[1] = (Real)((int)(floor(pos_ref[1] / dh))) * dh;
311 a[2] = (Real)((int)(floor(pos_ref[2] / dh))) * dh;
314 for (int i = 0; i < 27; i++)
316 anchorPoint[id * 27 + i] = Coord( a[0] + dh * Real(diff_v[i][0]),
317 a[1] + dh * Real(diff_v[i][1]),
318 a[2] + dh * Real(diff_v[i][2])
325*@brief Virtual particles' candinate points
326* Every particle has 33 neighbors.
328 template<typename Real, typename Coord>
329 __global__ void AFV_AnchorNeighbor_33
331 DArray<Coord> anchorPoint,
337 int id = threadIdx.x + (blockIdx.x * blockDim.x);
338 if (id >= pos.size()) return;
340 //Coord pos_ref = pos[id] - origin + dh / 2;
341 Coord pos_ref = pos[id] - origin + dh / 2;
344 a[0] = (Real)((int)(floor(pos_ref[0] / dh))) * dh;
345 a[1] = (Real)((int)(floor(pos_ref[1] / dh))) * dh;
346 a[2] = (Real)((int)(floor(pos_ref[2] / dh))) * dh;
349 for (int i = 0; i < 33; i++)
351 anchorPoint[id * 33 + i] = Coord(a[0] + dh * Real(diff_v_33[i][0]),
352 a[1] + dh * Real(diff_v_33[i][1]),
353 a[2] + dh * Real(diff_v_33[i][2])
360*@brief Virtual particles' candinate points
361* Every particle has 125 neighbors.
363 template<typename Real, typename Coord>
364 __global__ void AFV_AnchorNeighbor_125
366 DArray<Coord> anchorPoint,
372 int id = threadIdx.x + (blockIdx.x * blockDim.x);
373 if (id >= pos.size()) return;
375 Coord pos_ref = pos[id] - origin + dh / 2;
378 a[0] = (Real)((int)(floor(pos_ref[0] / dh))) * dh;
379 a[1] = (Real)((int)(floor(pos_ref[1] / dh))) * dh;
380 a[2] = (Real)((int)(floor(pos_ref[2] / dh))) * dh;
383 for (int i = 0; i < 125; i++)
385 anchorPoint[id * 125 + i] = Coord(a[0] + dh * Real(diff_v_125[i][0]),
386 a[1] + dh * Real(diff_v_125[i][1]),
387 a[2] + dh * Real(diff_v_125[i][2])
394 template< typename Coord>
395 __global__ void AFV_PositionToMortonCode_TEST
397 DArray<uint32_t> mortonCode,
398 DArray<Coord> gridPoint,
402 int id = threadIdx.x + (blockIdx.x * blockDim.x);
403 if (id >= gridPoint.size()) return;
405 uint32_t x = (uint32_t)(gridPoint[id][0] / dh);
406 uint32_t y = (uint32_t)(gridPoint[id][1] / dh);
407 uint32_t z = (uint32_t)(gridPoint[id][2] / dh);
416 xi = (xi | (xi << 16)) & 0x030000FF;
417 xi = (xi | (xi << 8)) & 0x0300F00F;
418 xi = (xi | (xi << 4)) & 0x030C30C3;
419 xi = (xi | (xi << 2)) & 0x09249249;
421 yi = (yi | (yi << 16)) & 0x030000FF;
422 yi = (yi | (yi << 8)) & 0x0300F00F;
423 yi = (yi | (yi << 4)) & 0x030C30C3;
424 yi = (yi | (yi << 2)) & 0x09249249;
426 zi = (zi | (zi << 16)) & 0x030000FF;
427 zi = (zi | (zi << 8)) & 0x0300F00F;
428 zi = (zi | (zi << 4)) & 0x030C30C3;
429 zi = (zi | (zi << 2)) & 0x09249249;
431 key = xi | (yi << 1) | (zi << 2);
433 uint32_t xv = key & 0x09249249;
434 uint32_t yv = (key >> 1) & 0x09249249;
435 uint32_t zv = (key >> 2) & 0x09249249;
437 xv = ((xv >> 2) | xv) & 0x030C30C3;
438 xv = ((xv >> 4) | xv) & 0x0300F00F;
439 xv = ((xv >> 8) | xv) & 0x030000FF;
440 xv = ((xv >> 16) | xv) & 0x000003FF;
442 yv = ((yv >> 2) | yv) & 0x030C30C3;
443 yv = ((yv >> 4) | yv) & 0x0300F00F;
444 yv = ((yv >> 8) | yv) & 0x030000FF;
445 yv = ((yv >> 16) | yv) & 0x000003FF;
447 zv = ((zv >> 2) | zv) & 0x030C30C3;
448 zv = ((zv >> 4) | zv) & 0x0300F00F;
449 zv = ((zv >> 8) | zv) & 0x030000FF;
450 zv = ((zv >> 16) | zv) & 0x000003FF;
452 if(x!=xv || y!=yv || z!=zv)
453 printf("gridPoint: %d, %d, %d || key: %d || invert: %d, %d, %d \r\n", x, y, z, key, xv, yv, zv);
458 *@brief Positions(3-dimension) convert to Morton Codes
460 template< typename Coord>
461 __global__ void AFV_PositionToMortonCode
463 DArray<uint32_t> mortonCode,
464 DArray<Coord> gridPoint,
468 int id = threadIdx.x + (blockIdx.x * blockDim.x);
469 if (id >= gridPoint.size()) return;
471 uint32_t x = (uint32_t)(gridPoint[id][0] / dh + 100 * EPSILON);
472 uint32_t y = (uint32_t)(gridPoint[id][1] / dh + 100 * EPSILON);
473 uint32_t z = (uint32_t)(gridPoint[id][2] / dh + 100 * EPSILON);
482 xi = (xi | (xi << 16)) & 0x030000FF;
483 xi = (xi | (xi << 8)) & 0x0300F00F;
484 xi = (xi | (xi << 4)) & 0x030C30C3;
485 xi = (xi | (xi << 2)) & 0x09249249;
487 yi = (yi | (yi << 16)) & 0x030000FF;
488 yi = (yi | (yi << 8)) & 0x0300F00F;
489 yi = (yi | (yi << 4)) & 0x030C30C3;
490 yi = (yi | (yi << 2)) & 0x09249249;
492 zi = (zi | (zi << 16)) & 0x030000FF;
493 zi = (zi | (zi << 8)) & 0x0300F00F;
494 zi = (zi | (zi << 4)) & 0x030C30C3;
495 zi = (zi | (zi << 2)) & 0x09249249;
497 key = xi | (yi << 1) | (zi << 2);
499 mortonCode[id] = key;
504 *@brief Morton Codes convert to Positions(3-dimension)
506 template< typename Coord>
507 __global__ void AFV_MortonCodeToPosition
509 DArray<Coord> gridPoint,
510 DArray<uint32_t> mortonCode,
514 int id = threadIdx.x + (blockIdx.x * blockDim.x);
515 if (id >= mortonCode.size()) return;
518 uint32_t key = mortonCode[id];
520 uint32_t xv = key & 0x09249249;
521 uint32_t yv = (key >> 1) & 0x09249249;
522 uint32_t zv = (key >> 2) & 0x09249249;
524 xv = ((xv >> 2) | xv) & 0x030C30C3;
525 xv = ((xv >> 4) | xv) & 0x0300F00F;
526 xv = ((xv >> 8) | xv) & 0x030000FF;
527 xv = ((xv >> 16) | xv) & 0x000003FF;
529 yv = ((yv >> 2) | yv) & 0x030C30C3;
530 yv = ((yv >> 4) | yv) & 0x0300F00F;
531 yv = ((yv >> 8) | yv) & 0x030000FF;
532 yv = ((yv >> 16) | yv) & 0x000003FF;
534 zv = ((zv >> 2) | zv) & 0x030C30C3;
535 zv = ((zv >> 4) | zv) & 0x0300F00F;
536 zv = ((zv >> 8) | zv) & 0x030000FF;
537 zv = ((zv >> 16) | zv) & 0x000003FF;
539 Real x = (float)(xv)* dh;
540 Real y = (float)(yv)* dh;
541 Real z = (float)(zv)* dh;
543 gridPoint[id] = Coord(x, y, z);
548 *@brief Search for adjacent elements with the same value
550 __global__ void AFV_RepeatedElementSearch
552 DArray<uint32_t> morton,
553 DArray<uint32_t> counter
556 int id = threadIdx.x + (blockIdx.x * blockDim.x);
557 if (id >= morton.size()) return;
560 if (id == 0 || morton[id] != morton[id - 1])
569 *@brief Accumulate the number of non-repeating elements
571 __global__ void AFV_nonRepeatedElementsCal
573 DArray<uint32_t> non_repeated_elements,
574 DArray<uint32_t> post_elements,
575 DArray<uint32_t> counter
578 int id = threadIdx.x + (blockIdx.x * blockDim.x);
579 if (id >= post_elements.size()) return;
581 if (id == 0 || post_elements[id] != post_elements[id - 1])
583 non_repeated_elements[counter[id]] = post_elements[id];
590 template< typename Coord>
591 __global__ void AFV_CopyToVpos(
594 DArray<Coord> elements
598 int id = threadIdx.x + (blockIdx.x * blockDim.x);
599 if (id >= elements.size()) return;
600 vpos[id] = elements[id] + origin;
604 __global__ void AFV_ElementsPrint(
605 DArray<uint32_t> elements
608 int id = threadIdx.x + (blockIdx.x * blockDim.x);
609 if (id >= elements.size()) return;
613 printf("size: %d \r\n", elements.size());
614 for(int i = 0; i < elements.size(); i++)
615 printf("%d\t", elements[i]);
620 template< typename Real>
621 __global__ void AFV_SortMortonCodePrint
623 DArray<uint32_t> mortonCode,
624 DArray<uint32_t> counter,
628 int id = threadIdx.x + (blockIdx.x * blockDim.x);
629 if (id >= mortonCode.size()) return;
633 for (int i = 0; i < mortonCode.size(); i++)
635 printf("%d , %d \t", counter[i], mortonCode[i]);
642 template<typename TDataType>
643 void VirtualSpatiallyAdaptiveStrategy<TDataType>::constrain()
645 cudaDeviceSynchronize();
646 gridSize = this->varSamplingDistance()->getData();
647 int num = this->inRPosition()->size();
648 if (num == 0) return;
650 if (num == 0) return;
652 int node_num = num * (int)(this->varCandidatePointCount()->getDataPtr()->currentKey());
654 if (m_anchorPoint.size() != node_num)
656 m_anchorPoint.resize(node_num);
659 if (m_anchorPointCodes.size() != node_num)
661 m_anchorPointCodes.resize(node_num);
664 if (m_nonRepeatedCount.size() != node_num)
666 m_nonRepeatedCount.resize(node_num);
669 Reduction<Coord> reduce;
670 Coord hiBound = reduce.maximum(this->inRPosition()->getData().begin(), this->inRPosition()->getData().size());
671 Coord loBound = reduce.minimum(this->inRPosition()->getData().begin(), this->inRPosition()->getData().size());
674 hiBound += Coord((padding + 1)* gridSize);
675 loBound -= Coord(padding * gridSize);
677 loBound[0] = (Real)((int)(floor(loBound[0] / gridSize)))*gridSize;
678 loBound[1] = (Real)((int)(floor(loBound[1] / gridSize)))*gridSize;
679 loBound[2] = (Real)((int)(floor(loBound[2] / gridSize)))*gridSize;
681 origin = Coord(loBound[0], loBound[1], loBound[2]);
683 if (this->varCandidatePointCount()->getValue() == CandidatePointCount::neighbors_8) {
684 cuExecute(this->inRPosition()->getData().size(),
685 AFV_AnchorNeighbor_8,
687 this->inRPosition()->getData(),
693 else if (this->varCandidatePointCount()->getValue() == CandidatePointCount::neighbors_27) {
694 cuExecute(this->inRPosition()->getData().size(),
695 AFV_AnchorNeighbor_27,
697 this->inRPosition()->getData(),
702 else if (this->varCandidatePointCount()->getValue() == CandidatePointCount::neighbors_33) {
703 cuExecute(this->inRPosition()->getData().size(),
704 AFV_AnchorNeighbor_33,
706 this->inRPosition()->getData(),
711 else if (this->varCandidatePointCount()->getValue() == CandidatePointCount::neighbors_125) {
712 cuExecute(this->inRPosition()->getData().size(),
713 AFV_AnchorNeighbor_125,
715 this->inRPosition()->getData(),
722 std::cout << "*VIRTUAL PARTICLE:: AdaptiveVirtualPosition ERROR!!!!!" << std::endl;
725 cuExecute(m_anchorPointCodes.size(),
726 AFV_PositionToMortonCode,
732 thrust::sort(thrust::device, m_anchorPointCodes.begin(), m_anchorPointCodes.begin() + m_anchorPointCodes.size());
734 cuExecute(m_anchorPointCodes.size(),
735 AFV_RepeatedElementSearch,
741 int candidatePoint_num = thrust::reduce(thrust::device, m_nonRepeatedCount.begin(), m_nonRepeatedCount.begin() + m_nonRepeatedCount.size(), (int)0, thrust::plus<uint32_t>());
743 thrust::exclusive_scan(thrust::device, m_nonRepeatedCount.begin(), m_nonRepeatedCount.begin() + m_nonRepeatedCount.size(), m_nonRepeatedCount.begin());
745 m_candidateCodes.resize(candidatePoint_num);
748 cuExecute(m_anchorPointCodes.size(),
749 AFV_nonRepeatedElementsCal,
757 m_virtual_position.resize(m_candidateCodes.size());
759 cuExecute(m_candidateCodes.size(),
760 AFV_MortonCodeToPosition,
767 if (this->outVirtualParticles()->isEmpty())
769 this->outVirtualParticles()->allocate();
772 this->outVirtualParticles()->resize(m_virtual_position.size());
774 cuExecute(m_virtual_position.size(),
776 this->outVirtualParticles()->getData(),
781 std::cout << "*DUAL-ISPH::SpatiallyAdaptiveStrategy(S.C.)::Model_"<< this->varCandidatePointCount()->getDataPtr()->currentKey()
782 <<"::RealPoints:" << this->inRPosition()->size() << "||VirtualPoints:" << this->outVirtualParticles()->size() <<std::endl;
787 DEFINE_CLASS(VirtualSpatiallyAdaptiveStrategy);