1#include "CapillaryWave.h"
5#include "Mapping/HeightFieldToTriangleSet.h"
6#include "GLSurfaceVisualModule.h"
10 template<typename TDataType>
11 CapillaryWave<TDataType>::CapillaryWave()
14 auto heights = std::make_shared<HeightField<TDataType>>();
15 this->stateHeightField()->setDataPtr(heights);
17 auto mapper = std::make_shared<HeightFieldToTriangleSet<DataType3f>>();
18 this->stateHeightField()->connect(mapper->inHeightField());
19 this->graphicsPipeline()->pushModule(mapper);
21 // mapper->varScale()->setValue(0.1);
22 // mapper->varTranslation()->setValue(Vec3f(-2, 0.2, -2));
24 auto sRender = std::make_shared<GLSurfaceVisualModule>();
25 sRender->setColor(Color(0, 0.2, 1.0));
26 mapper->outTriangleSet()->connect(sRender->inTriangleSet());
27 this->graphicsPipeline()->pushModule(sRender);
30 template<typename TDataType>
31 CapillaryWave<TDataType>::~CapillaryWave()
34 mDeviceGridNext.clear();
37 template <typename Coord3D, typename Coord4D>
38 __global__ void CW_UpdateHeightDisp(
39 DArray2D<Coord3D> displacement,
40 DArray2D<Coord4D> dis)
42 unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
43 unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;
44 if (i < displacement.nx() && j < displacement.ny())
46 displacement(i, j).y = dis(i, j).x;
50 template <typename Coord>
51 __device__ float C_GetU(Coord gp)
53 Real h = max(gp.x, 0.0f);
56 Real h4 = h * h * h * h;
57 return sqrtf(2.0f) * h * uh / (sqrtf(h4 + max(h4, EPSILON)));
60 template <typename Coord>
61 __device__ Real C_GetV(Coord gp)
63 Real h = max(gp.x, 0.0f);
66 Real h4 = h * h * h * h;
67 return sqrtf(2.0f) * h * vh / (sqrtf(h4 + max(h4, EPSILON)));
70 template <typename Coord>
71 __global__ void CW_MoveSimulatedRegion(
72 DArray2D<Coord> grid_next,
80 int i = threadIdx.x + blockIdx.x * blockDim.x;
81 int j = threadIdx.y + blockIdx.y * blockDim.y;
82 if (i < width && j < height)
87 Coord gp = grid(gx, gy);
88 Coord gp_init = Coord(level, 0.0f, 0.0f, gp.w);
93 if (new_i < 0 || new_i >= width) gp = gp_init;
95 new_i = new_i % width;
96 if (new_i < 0) new_i = width + new_i;
98 if (new_j < 0 || new_j >= height) gp = gp_init;
100 new_j = new_j % height;
101 if (new_j < 0) new_j = height + new_j;
103 grid(new_i + 1, new_j + 1) = gp;
107 template<typename TDataType>
108 void CapillaryWave<TDataType>::moveDynamicRegion(int nx, int ny)
110 auto res = this->varResolution()->getValue();
112 auto level = this->varWaterLevel()->getValue();
117 cuExecute2D(make_uint2(extNx, extNy),
118 CW_MoveSimulatedRegion,
131 template<typename TDataType>
132 void CapillaryWave<TDataType>::resetStates()
134 int res = this->varResolution()->getValue();
135 Real length = this->varLength()->getValue();
137 Real level = this->varWaterLevel()->getValue();
139 mRealGridSize = length / res;
144 mDeviceGrid.resize(extNx, extNy);
145 mDeviceGridNext.resize(extNx, extNy);
146 this->stateHeight()->resize(res, res);
148 //init grid with initial values
149 cuExecute2D(make_uint2(extNx, extNy),
156 //init grid_next with initial values
157 cuExecute2D(make_uint2(extNx, extNy),
164 auto topo = this->stateHeightField()->getDataPtr();
165 topo->setExtents(res, res);
166 topo->setGridSpacing(mRealGridSize);
167 topo->setOrigin(Coord3D(-0.5 * mRealGridSize * topo->width(), 0, -0.5 * mRealGridSize * topo->height()));
169 auto& disp = topo->getDisplacement();
172 extent.x = disp.nx();
173 extent.y = disp.ny();
177 this->stateHeight()->getData(),
183 template<typename TDataType>
184 void CapillaryWave<TDataType>::updateStates()
186 Real dt = this->stateTimeStep()->getValue();
188 Real level = this->varWaterLevel()->getValue();
190 uint res = this->varResolution()->getValue();
196 float timestep = dt / nStep;
198 auto scn = this->getSceneGraph();
199 auto GRAVITY = scn->getGravity().norm();
201 for (int iter = 0; iter < nStep; iter++)
203 cuExecute2D(make_uint2(extNx, extNy),
210 cuExecute2D(make_uint2(res, res),
220 cuExecute2D(make_uint2(res, res),
222 this->stateHeight()->getData(),
227 cuExecute2D(make_uint2(res, res),
229 this->stateHeight()->getData(),
233 auto topo = this->stateHeightField()->getDataPtr();
235 auto& disp = topo->getDisplacement();
238 extent.x = disp.nx();
239 extent.y = disp.ny();
244 this->stateHeight()->getData());
247 template <typename Coord4D>
248 __global__ void InitDynamicRegion(DArray2D<Coord4D> grid, int gridwidth, int gridheight, float level)
250 int x = threadIdx.x + blockIdx.x * blockDim.x;
251 int y = threadIdx.y + blockIdx.y * blockDim.y;
252 if (x < gridwidth && y < gridheight)
261// if ((x - 256) * (x - 256) + (y - 256) * (y - 256) <= 2500) grid(x, y).x = level;
265 template <typename Coord4D>
266 __global__ void CW_ImposeBC(
267 DArray2D<Coord4D> grid_next,
268 DArray2D<Coord4D> grid,
272 int x = threadIdx.x + blockIdx.x * blockDim.x;
273 int y = threadIdx.y + blockIdx.y * blockDim.y;
274 if (x < width && y < height)
278 Coord4D a = grid(1, y);
281 else if (x == width - 1)
283 Coord4D a = grid(width - 2, y);
288 Coord4D a = grid(x, 1);
291 else if (y == height - 1)
293 Coord4D a = grid(x, height - 2);
298 Coord4D a = grid(x, y);
304 template <typename Coord>
305 __host__ __device__ void CW_FixShore(Coord& l, Coord& c, Coord& r)
308 if (r.x < 0.0f || l.x < 0.0f || c.x < 0.0f)
310 c.x = c.x + l.x + r.x;
311 c.x = max(0.0f, c.x);
316 float h4 = h * h * h * h;
317 float v = sqrtf(2.0f) * h * c.y / (sqrtf(h4 + max(h4, EPSILON)));
318 float u = sqrtf(2.0f) * h * c.z / (sqrtf(h4 + max(h4, EPSILON)));
324 template <typename Coord>
325 __host__ __device__ Coord CW_VerticalPotential(Coord gp, float GRAVITY)
327 float h = max(gp.x, 0.0f);
331 float h4 = h * h * h * h;
332 float v = sqrtf(2.0f) * h * vh / (sqrtf(h4 + max(h4, EPSILON)));
337 G.z = vh * v + GRAVITY * h * h;
342 template <typename Coord>
343 __device__ Coord CW_HorizontalPotential(Coord gp, float GRAVITY)
345 float h = max(gp.x, 0.0f);
349 float h4 = h * h * h * h;
350 float u = sqrtf(2.0f) * h * uh / (sqrtf(h4 + max(h4, EPSILON)));
354 F.y = uh * u + GRAVITY * h * h;
360 template <typename Coord>
361 __device__ Coord CW_SlopeForce(Coord c, Coord n, Coord e, Coord s, Coord w, float GRAVITY)
363 float h = max(c.x, 0.0f);
367 H.y = -GRAVITY * h * (e.w - w.w);
368 H.z = -GRAVITY * h * (s.w - n.w);
373 template <typename Coord4D>
374 __global__ void CW_OneWaveStep(
375 DArray2D<Coord4D> grid_next,
376 DArray2D<Coord4D> grid,
382 int x = threadIdx.x + blockIdx.x * blockDim.x;
383 int y = threadIdx.y + blockIdx.y * blockDim.y;
385 if (x < width && y < height)
390 Coord4D center = grid(gridx, gridy);
392 Coord4D north = grid(gridx, gridy - 1);
394 Coord4D west = grid(gridx - 1, gridy);
396 Coord4D south = grid(gridx, gridy + 1);
398 Coord4D east = grid(gridx + 1, gridy);
400 CW_FixShore(west, center, east);
401 CW_FixShore(north, center, south);
403 Coord4D u_south = 0.5f * (south + center) - timestep * (CW_VerticalPotential(south, GRAVITY) - CW_VerticalPotential(center, GRAVITY));
404 Coord4D u_north = 0.5f * (north + center) - timestep * (CW_VerticalPotential(center, GRAVITY) - CW_VerticalPotential(north, GRAVITY));
405 Coord4D u_west = 0.5f * (west + center) - timestep * (CW_HorizontalPotential(center, GRAVITY) - CW_HorizontalPotential(west, GRAVITY));
406 Coord4D u_east = 0.5f * (east + center) - timestep * (CW_HorizontalPotential(east, GRAVITY) - CW_HorizontalPotential(center, GRAVITY));
408 Coord4D u_center = center + timestep * CW_SlopeForce(center, north, east, south, west, GRAVITY) - timestep * (CW_HorizontalPotential(u_east, GRAVITY) - CW_HorizontalPotential(u_west, GRAVITY)) - timestep * (CW_VerticalPotential(u_south, GRAVITY) - CW_VerticalPotential(u_north, GRAVITY));
409 u_center.x = max(0.0f, u_center.x);
411 grid_next(gridx, gridy) = u_center;
415 template <typename Coord>
416 __global__ void CW_InitHeights(
417 DArray2D<Coord> height,
418 DArray2D<Coord> grid,
422 int i = threadIdx.x + blockIdx.x * blockDim.x;
423 int j = threadIdx.y + blockIdx.y * blockDim.y;
424 if (i < patchSize && j < patchSize)
429 Coord gp = grid(gridx, gridy);
434 template <typename Coord4D>
435 __global__ void CW_InitHeightGrad(
436 DArray2D<Coord4D> height,
439 int i = threadIdx.x + blockIdx.x * blockDim.x;
440 int j = threadIdx.y + blockIdx.y * blockDim.y;
441 if (i < patchSize && j < patchSize)
443 int i_minus_one = (i - 1 + patchSize) % patchSize;
444 int i_plus_one = (i + 1) % patchSize;
445 int j_minus_one = (j - 1 + patchSize) % patchSize;
446 int j_plus_one = (j + 1) % patchSize;
448 Coord4D Dx = (height(i_plus_one, j) - height(i_minus_one, j)) / 2;
449 Coord4D Dz = (height(i, j_plus_one) - height(i, j_minus_one)) / 2;
451 height(i, j).z = Dx.y;
452 height(i, j).w = Dz.y;
456 template <typename Real, typename Coord3D, typename Coord4D>
457 __global__ void CW_InitHeightDisp(
458 DArray2D<Coord4D> heights,
459 DArray2D<Coord3D> displacement,
460 DArray2D<Coord4D> grid,
463 unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
464 unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;
465 if (i < displacement.nx() && j < displacement.ny())
470 Coord4D gij = grid(gridx, gridy);
472 displacement(i, j).x = 0;
473 displacement(i, j).y = gij.x + gij.w;
474 displacement(i, j).z = 0;
480 DEFINE_CLASS(CapillaryWave);