PeriDyno 1.0.0
Loading...
Searching...
No Matches
Wake.cu
Go to the documentation of this file.
1#include "Wake.h"
2
3#include "Math/Lerp.h"
4
5#include "Algorithm/CudaRand.h"
6
7namespace dyno
8{
9 IMPLEMENT_TCLASS(Wake, TDataType)
10
11 template<typename TDataType>
12 Wake<TDataType>::Wake()
13 : CapillaryWave<TDataType>()
14 {
15 this->setAutoHidden(true);
16 }
17
18 template<typename TDataType>
19 Wake<TDataType>::~Wake()
20 {
21 }
22
23 template <typename Real, typename Coord2D, typename Coord3D, typename Coord4D, typename TriangleIndex>
24 __global__ void W_AccumlateTrails(
25 DArray2D<Coord2D> sources,
26 DArray2D<Real> weights,
27 DArray2D<Coord4D> grid,
28 DArray<Coord3D> vertices,
29 DArray<TriangleIndex> indices,
30 Coord3D waveOrigin,
31 Coord3D vesselCenter,
32 Coord3D vesselVelocity,
33 Coord3D vesselAngularVelocity,
34 Real spacing)
35 {
36 int tId = threadIdx.x + blockIdx.x * blockDim.x;
37 if (tId >= indices.size()) return;
38
39 TriangleIndex index_i = indices[tId];
40
41 Coord3D v0 = vertices[index_i[0]];
42 Coord3D v1 = vertices[index_i[1]];
43 Coord3D v2 = vertices[index_i[2]];
44
45 Coord3D tc = (v0 + v1 + v2) / Real(3);
46
47 uint nx = grid.nx();
48 uint ny = grid.ny();
49
50 Real x = (tc.x - waveOrigin.x) / spacing;
51 Real y = (tc.z - waveOrigin.z) / spacing;
52
53 Coord3D vel = vesselVelocity + (tc - vesselCenter).cross(vesselAngularVelocity);
54
55 Coord4D g_i = bilinear(grid, x, y, LerpMode::CLAMP_TO_BORDER);
56
57 //If the center is above the water surface, no impulse will be imposed
58 Real d = (g_i.x - tc.y);
59 d = d < 0 ? 0 : d;
60
61 uint i0 = floor(x);
62 uint j0 = floor(y);
63
64 Real fx = x - i0;
65 Real fy = y - j0;
66
67 uint i1 = i0 + 1;
68 uint j1 = j0 + 1;
69
70 i0 = i0 < 1 ? 1 : (i0 >= nx - 2 ? nx - 2 : i0);
71 j0 = j0 < 1 ? 1 : (j0 >= ny - 2 ? ny - 2 : j0);
72
73 i1 = i1 < 1 ? 1 : (i1 >= nx - 2 ? nx - 2 : i1);
74 j1 = j1 < 1 ? 1 : (j1 >= ny - 2 ? ny - 2 : j1);
75
76 Real hu = d * vel.x;
77 Real hv = d * vel.z;
78
79 const float w00 = (1.0f - fx) * (1.0f - fy);
80 const float w10 = fx * (1.0f - fy);
81 const float w01 = (1.0f - fx) * fy;
82 const float w11 = fx * fy;
83
84 atomicAdd(&sources(i0, j0).x, w00 * hu);
85 atomicAdd(&sources(i0, j0).y, w00 * hv);
86 atomicAdd(&weights(i0, j0), w00);
87
88 atomicAdd(&sources(i0, j1).x, w01 * hu);
89 atomicAdd(&sources(i0, j1).y, w01 * hv);
90 atomicAdd(&weights(i0, j1), w01);
91
92 atomicAdd(&sources(i1, j0).x, w10 * hu);
93 atomicAdd(&sources(i1, j0).y, w10 * hv);
94 atomicAdd(&weights(i1, j0), w10);
95
96 atomicAdd(&sources(i1, j1).x, w11 * hu);
97 atomicAdd(&sources(i1, j1).y, w11 * hv);
98 atomicAdd(&weights(i1, j1), w11);
99 }
100
101 template <typename Real, typename Coord2D, typename Coord4D>
102 __global__ void W_AddTrails(
103 DArray2D<Coord2D> sources,
104 DArray2D<Real> weights,
105 DArray2D<Coord4D> grid,
106 Real mag)
107 {
108 int i = threadIdx.x + blockIdx.x * blockDim.x;
109 int j = threadIdx.y + blockIdx.y * blockDim.y;
110
111 if (i < grid.nx() && j < grid.ny())
112 {
113 //if (weights(i, j) > 1)
114 {
115 RandNumber gen(i * j);
116
117 auto rnd = gen.Generate();
118
119 Coord4D gij = grid(i, j);
120 Coord2D sij = weights(i, j) > 1 ? sources(i, j) / weights(i, j) : sources(i, j);
121
122 gij.y += mag * rnd * sij.x;
123 gij.z += mag * rnd * sij.y;
124
125 grid(i, j) = gij;
126 }
127 }
128 }
129
130 template<typename TDataType>
131 void Wake<TDataType>::addTrails()
132 {
133 uint res = this->varResolution()->getValue();
134
135 Real dt = this->stateTimeStep()->getValue();
136
137 auto heights = this->stateHeightField()->getDataPtr();
138 auto& displacements = heights->getDisplacement();
139 auto waveOrigin = heights->getOrigin();
140 auto h = heights->getGridSpacing();
141
142 {
143 auto vessel = this->getVessel();
144 auto& triangles = vessel->stateEnvelope()->getData();
145
146 auto vesselCenter = vessel->stateCenter()->getData();
147 auto vesselVelocity = vessel->stateVelocity()->getData();
148 auto avesselAngularVelocity = vessel->stateAngularVelocity()->getData();
149
150 auto& vertices = triangles.getPoints();
151 auto& indices = triangles.getTriangles();
152
153 uint num = indices.size();
154
155 if (this->mDeviceGrid.nx() != mWeight.nx() || this->mDeviceGrid.ny() != mWeight.ny())
156 {
157 mWeight.resize(this->mDeviceGrid.nx(), this->mDeviceGrid.ny());
158 mSource.resize(this->mDeviceGrid.nx(), this->mDeviceGrid.ny());
159 }
160
161 mWeight.reset();
162 mSource.reset();
163
164 cuExecute(num,
165 W_AccumlateTrails,
166 mSource,
167 mWeight,
168 this->mDeviceGrid,
169 vertices,
170 indices,
171 waveOrigin,
172 vesselCenter,
173 vesselVelocity,
174 avesselAngularVelocity,
175 h);
176
177 Real mag = this->varMagnitude()->getValue();
178
179 cuExecute2D(make_uint2(this->mDeviceGrid.nx(), this->mDeviceGrid.ny()),
180 W_AddTrails,
181 mSource,
182 mWeight,
183 this->mDeviceGrid,
184 mag);
185
186 this->mDeviceGridNext.assign(this->mDeviceGrid);
187 }
188 }
189
190 template<typename TDataType>
191 void Wake<TDataType>::updateStates()
192 {
193 if (this->getVessel() != nullptr)
194 addTrails();
195
196 CapillaryWave<TDataType>::updateStates();
197 }
198
199 DEFINE_CLASS(Wake);
200}