You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: DOCUMENTATION.md
+10-17Lines changed: 10 additions & 17 deletions
Original file line number
Diff line number
Diff line change
@@ -386,29 +386,22 @@
386
386
387
387
### Lift/Drag Forces
388
388
- Enable (uncomment) the [`FORCE_FIELD`](src/defines.hpp) extension. This extension allows computing boundary forces on every solid cell (`TYPE_S`) individually, as well as placing an individual volume force on every fluid cell (not used here).
389
-
- In the [`main_setup()`](src/setup.cpp) function's main simulation loop, alternatingly call:
389
+
- In the [`main_setup()`](src/setup.cpp) function, voxelize the mesh with a unique flag combination, such as `(TYPE_S|TYPE_X)` or `(TYPE_S|TYPE_Y)` or `(TYPE_S|TYPE_X|TYPE_Y)`, to distinguish it from all other `(TYPE_S)` cells that might be needed to define other geometry, and compute its center of mass:
390
390
```c
391
-
lbm.run(lbm_dt); // run lbm_dt LBM time steps
392
-
lbm.calculate_force_on_boundaries(); // compute boundary forces on GPU on all solid cells (TYPE_S)
391
+
lbm.voxelize_mesh_on_device(mesh, TYPE_S|TYPE_X); // voxelize mesh with unique flag combination
392
+
const float3 lbm_com = lbm.object_center_of_mass(TYPE_S|TYPE_X); // object center of mass in LBM unit coordinates
393
393
```
394
-
The latter computes the boundary forces on the GPU into the `lbm.F` field in VRAM.
395
-
- To copy `lbm.F` from GPU VRAM to CPU RAM, call:
394
+
- To sum over all the individual boundary cells that belong to the object, in the [`main_setup()`](src/setup.cpp) function's main simulation loop call:
396
395
```c
397
-
lbm.F.read_from_device();
396
+
const float3 lbm_force = lbm.object_force(TYPE_S|TYPE_X); // force on object
397
+
const float3 lbm_torque = lbm.object_torque(lbm_com, TYPE_S|TYPE_X); // torque on object around lbm_com rotation point
398
398
```
399
-
You can then access the boundary forces at each individual cell with:
399
+
These functions sum over all cells marked `(TYPE_S|TYPE_X)` that belong to the object. The summation happens GPU-accelerated in VRAM, and only the result is copied to CPU RAM.
400
+
- You may also access the force field on individual grid cells. Note that copying the entire `lbm.F` force field from GPU VRAM to CPU RAM is slow:
400
401
```c
401
-
float lbm_force_x_n = lbm.F.x[lbm.index(x, y, z)];
402
+
lbm.F.read_from_device(); // copy entire force field from GPU VRAM to CPU RAM (slow)
403
+
lbm_force_x_n = lbm.F.x[lbm.index(x, y, z)]; // access force at one particular grid cell with integer coordinates x, y, z
402
404
```
403
-
- To sum over all the individual boundary cells that belong to the body, to get the total force on the body, first voxelize the body with
404
-
```c
405
-
lbm.voxelize_mesh_on_device(mesh, TYPE_S|TYPE_X);
406
-
```
407
-
with the additional `TYPE_X` flagging, and then call
Copy file name to clipboardExpand all lines: src/defines.hpp
+3-3Lines changed: 3 additions & 3 deletions
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@
16
16
#defineBENCHMARK// disable all extensions and setups and run benchmark setup instead
17
17
18
18
//#define VOLUME_FORCE // enables global force per volume in one direction (equivalent to a pressure gradient); specified in the LBM class constructor; the force can be changed on-the-fly between time steps at no performance cost
19
-
//#define FORCE_FIELD // enables computing the forces on solid boundaries with lbm.calculate_force_on_boundaries(); and enables setting the force for each lattice point independently (enable VOLUME_FORCE too); allocates an extra 12 Bytes/cell
19
+
//#define FORCE_FIELD // enables computing the forces on solid boundaries with lbm.update_force_field(); and enables setting the force for each lattice point independently (enable VOLUME_FORCE too); allocates an extra 12 Bytes/cell
20
20
//#define EQUILIBRIUM_BOUNDARIES // enables fixing the velocity/density by marking cells with TYPE_E; can be used for inflow/outflow; does not reflect shock waves
21
21
//#define MOVING_BOUNDARIES // enables moving solids: set solid cells to TYPE_S and set their velocity u unequal to zero
22
22
//#define SURFACE // enables free surface LBM: mark fluid cells with TYPE_F; at initialization the TYPE_I interface and TYPE_G gas domains will automatically be completed; allocates an extra 12 Bytes/cell
@@ -32,9 +32,9 @@
32
32
#defineGRAPHICS_FRAME_HEIGHT1080// set frame height if only GRAPHICS is enabled
33
33
#defineGRAPHICS_BACKGROUND_COLOR0x000000// set background color; black background (default) = 0x000000, white background = 0xFFFFFF
34
34
#defineGRAPHICS_U_MAX0.18f// maximum velocity for velocity coloring in units of LBM lattice speed of sound (c=1/sqrt(3)) (default: 0.18f)
35
-
#defineGRAPHICS_RHO_DELTA0.01f// coloring range for density rho will be [1.0f-GRAPHICS_RHO_DELTA, 1.0f+GRAPHICS_RHO_DELTA] (default: 0.01f)
35
+
#defineGRAPHICS_RHO_DELTA0.001f// coloring range for density rho will be [1.0f-GRAPHICS_RHO_DELTA, 1.0f+GRAPHICS_RHO_DELTA] (default: 0.001f)
36
36
#defineGRAPHICS_T_DELTA1.0f// coloring range for temperature T will be [1.0f-GRAPHICS_T_DELTA, 1.0f+GRAPHICS_T_DELTA] (default: 1.0f)
37
-
#defineGRAPHICS_F_MAX0.001f// maximum force in LBM units for visualization of forces on solid boundaries if VOLUME_FORCE is enabled and lbm.calculate_force_on_boundaries(); is called (default: 0.001f)
37
+
#defineGRAPHICS_F_MAX0.001f// maximum force in LBM units for visualization of forces on solid boundaries if VOLUME_FORCE is enabled and lbm.update_force_field(); is called (default: 0.001f)
38
38
#defineGRAPHICS_Q_CRITERION0.0001f// Q-criterion value for Q-criterion isosurface visualization (default: 0.0001f)
39
39
#defineGRAPHICS_STREAMLINE_SPARSE8// set how many streamlines there are every x lattice points
40
40
#defineGRAPHICS_STREAMLINE_LENGTH128// set maximum length of streamlines
//bool workgroup_any(const bool condition) { // returns true if any thread within the workgroup enters true
56
-
// volatile local uint workgroup_condition; // does not work on AMD GPUs (error: non-kernel function variable cannot be declared in local address space)
//bool workgroup_all(const bool condition) { // returns true if all threads within the workgroup enter true
64
-
// volatile local uint workgroup_condition; // does not work on AMD GPUs (error: non-kernel function variable cannot be declared in local address space)
@@ -1916,9 +1900,9 @@ string opencl_c_container() { return R( // ########################## begin of O
1916
1900
} // update_fields()
1917
1901
1918
1902
)+"#ifdef FORCE_FIELD"+R(
1919
-
)+R(kernel voidcalculate_force_on_boundaries(const global fpxx* fi, const global uchar* flags, const ulong t, global float* F) { // calculate force from the fluid on solid boundaries from fi directly
1903
+
)+R(kernel voidupdate_force_field(const global fpxx* fi, const global uchar* flags, const ulong t, global float* F) { // calculate force from the fluid on solid boundaries from fi directly
1920
1904
const uxx n = get_global_id(0); // n = x+(y+z*Ny)*Nx
1921
-
if(n>=(uxx)def_N||is_halo(n)) return; // don't execute calculate_force_on_boundaries() on halo
1905
+
if(n>=(uxx)def_N||is_halo(n)) return; // don't execute update_force_field() on halo
1922
1906
if((flags[n]&TYPE_BO)!=TYPE_S) return; // only continue for solid boundary cells
1923
1907
uxx j[def_velocity_set]; // neighbor indices
1924
1908
neighbors(n, j); // calculate neighbor indices
@@ -1929,19 +1913,15 @@ string opencl_c_container() { return R( // ########################## begin of O
1929
1913
F[ n] = 2.0f*fx*Fb; // 2 times because fi are reflected on solid boundary cells (bounced-back)
1930
1914
F[ def_N+(ulong)n] = 2.0f*fy*Fb;
1931
1915
F[2ul*def_N+(ulong)n] = 2.0f*fz*Fb;
1932
-
} //calculate_force_on_boundaries()
1916
+
} //update_force_field()
1933
1917
)+R(kernel voidreset_force_field(global float* F) { // reset force field
1934
1918
const uxx n = get_global_id(0); // n = x+(y+z*Ny)*Nx
1935
1919
if(n>=(uxx)def_N) return; // execute reset_force_field() also on halo
1936
1920
F[ n] = 0.0f;
1937
1921
F[ def_N+(ulong)n] = 0.0f;
1938
1922
F[2ul*def_N+(ulong)n] = 0.0f;
1939
1923
} // reset_force_field()
1940
-
)+"#endif"+R( // FORCE_FIELD
1941
-
1942
-
)+"#ifdef PARTICLES"+R(
1943
-
)+"#ifdef FORCE_FIELD"+R(
1944
-
voidatomic_add_f(volatile global float* addr, constfloat val) {
1924
+
)+R(voidatomic_add_f(volatile global float* addr, constfloat val) {
1945
1925
)+"#if cl_nv_compute_capability>=20"+R( // use hardware-supported atomic addition on Nvidia GPUs with inline PTX assembly
0 commit comments