PeriDyno 1.0.0
Loading...
Searching...
No Matches
ComputeParticleAnisotropy.cu
Go to the documentation of this file.
1 #include "ComputeParticleAnisotropy.h"
2#include "Matrix/MatrixFunc.h"
3
4namespace dyno
5{
6 template <typename Real>
7 DYN_FUNC inline Real iso_Weight(const Real r, const Real h)
8 {
9 const Real q = r / h;
10 if (q >= 1.0f) return 0.0f;
11 else {
12 return (1.0f - q*q*q);
13 }
14 }
15
16 template <typename Real, typename Coord, typename Transform>
17 __global__ void CalculateTransform(
18 DArray<Transform> transform,
19 DArray<Coord> pos,
20 DArrayList<int> neighbors,
21 Real smoothingLength)
22 {
23 int pId = threadIdx.x + (blockIdx.x * blockDim.x);
24 if (pId >= pos.size()) return;
25
26 Real totalWeight = 0;
27 Coord pos_i = pos[pId];
28
29
30 List<int>& list_i = neighbors[pId];
31 int nbSize = list_i.size();
32 Real total_weight = 0.0f;
33 Mat3f mat_i = Mat3f(0);
34
35 Coord W_pos_i = Coord(0);
36
37 Real total_weight1=0.0f;
38 for (int ne = 0; ne < nbSize; ne++)
39 {
40 int j = list_i[ne];
41 Real r = (pos_i - pos[j]).norm();
42 Real h = (2.0f)*smoothingLength;
43 Real weight = iso_Weight(r, h);
44 W_pos_i += pos[j] * weight;// smoothingLength;
45 total_weight1 += weight;
46 }
47 if (total_weight1> EPSILON)
48 {
49 W_pos_i *= (1.0f / total_weight1);
50 }
51
52 for (int ne = 0; ne < nbSize; ne++)
53 {
54 int j = list_i[ne];
55 Real r = (pos_i - pos[j]).norm();
56
57 if (r > EPSILON)
58 {
59 Real h = (1.0f)*smoothingLength;
60 Real weight = iso_Weight(r, h);
61 Coord q = (pos[j] - pos_i)*weight / smoothingLength;
62
63 mat_i(0, 0) += q[0] * q[0]; mat_i(0, 1) += q[0] * q[1]; mat_i(0, 2) += q[0] * q[2];
64 mat_i(1, 0) += q[1] * q[0]; mat_i(1, 1) += q[1] * q[1]; mat_i(1, 2) += q[1] * q[2];
65 mat_i(2, 0) += q[2] * q[0]; mat_i(2, 1) += q[2] * q[1]; mat_i(2, 2) += q[2] * q[2];
66
67 total_weight += weight;
68 }
69 }
70
71 if (total_weight > EPSILON)
72 {
73 mat_i *= (1.0f / total_weight);
74 }
75
76 Mat3f R(0), U(0), D(0), V(0);
77
78 polarDecomposition(mat_i, R, U, D, V);
79
80 Real e0 = D(0, 0);
81 Real e1 = D(1, 1);
82 Real e2 = D(2, 2);
83
84 Real threshold = 0.0001f;
85 Real minD = min(e0, min(e1, e2));
86 Real maxD = max(e0, max(e1, e2));
87 Real maxE = 0.824;
88 if (maxD > maxE)
89 {
90 maxE = maxD;
91 }
92 if (maxD < threshold)
93 {
94 D(0, 0) = maxE;
95 D(1, 1) = maxE;
96 D(2, 2) = maxE;
97 }
98 else
99 {
100 D(0, 0) = e0 / maxE;
101 D(1, 1) = e1 / maxE;
102 D(2, 2) = e2 / maxE;
103
104 if (e1 < threshold)
105 D(1, 1) = threshold;
106 if (e2 < threshold)
107 D(2, 2) = threshold;
108 }
109
110 Transform3f tm;
111 tm.translation() = pos[pId];
112 tm.rotation() = U;
113 tm.scale() = 0.02 * Vec3f(D(0, 0), D(1, 1), D(2, 2));
114 transform[pId] = tm;
115 }
116
117 template<typename TDataType>
118 ComputeParticleAnisotropy<TDataType>::ComputeParticleAnisotropy()
119 : ComputeModule()
120 {
121 this->varSmoothingLength()->setValue(Real(0.0125));
122
123 };
124
125 template<typename TDataType>
126 ComputeParticleAnisotropy<TDataType>::~ComputeParticleAnisotropy()
127 {
128 };
129
130 template<typename TDataType>
131 void ComputeParticleAnisotropy<TDataType>::compute()
132 {
133 int num = this->inPosition()->size();
134
135 if (this->outTransform()->size() != num) {
136 this->outTransform()->resize(num);
137 }
138
139 cuExecute(num,
140 CalculateTransform,
141 this->outTransform()->getData(),
142 this->inPosition()->getData(),
143 this->inNeighborIds()->getData(),
144 this->varSmoothingLength()->getData());
145 };
146
147 DEFINE_CLASS(ComputeParticleAnisotropy);
148}