• No results found

6.4 Velocity-Vortex Fire Implementation

6.4.3 Vorticity Dynamics

Once the spatial grid has been dynamically adjusted based on the current positions of the par- ticles in the system, the velocity values for each cell in the grid can be calculated. The spatial

grid is referred to as the velocity grid when talking about the velocity values. This step is

parallelized using one thread pergrid cellrather than the standard one thread per particle.

Velocity is calculated based on the vorticity of the particles contained in each grid cell. This step assumes the sorted arrays for particle indices have already been calculated. Given this assumption, the cell’s position in the grid is calculated using the cell’s own index number, which is then used to generate the list of possible neighbouring cells. Each of these cells (including the current cell) provide indices into thecell firstandcell lastarrays containing the sorted indices of particles contained in those cells. Altogether this provides a complete list of particles which will add velocity to the current cell. If the current cell is on a boundary in

any direction, the neighbouring cellsin the same directionshould not provide any additional

velocity, as the spatial grid does not wrap around on itself. In this case a simple check is

performed - if the cell is a boundary cell, the velocity accumulation for all neighbours in that particular direction is set to zero. Algorithm 6 shows this method in detail.

In the algorithm, the functionvelF romV ortis simplified and is shown in greater detail in

Listing 6.6. As explained in Section 4.4, velocity is due to vorticity is given using Biot-Savart’s law (See Equation 4.20). Notice that the velocity calculated uses the particles angular velocity, which is simply half the vorticity. One thing to note is that a check occurs in relation to the position of the vorton relative to the cell position. If it is very close, it is not desirable to induce a huge velocity due to the vorticity, so a corrected velocity is calculated.

As explained in Section 6.4, the change in vorticity (or vortex stretching) every timestep is dependent on the velocity of the fluid around the vorton. This step involves two main parts - firstly, the computation of the Jacobian matrix of the velocity in the cell in which the vorton resides, and then secondly applying the stress formula to find the new vorticity. Calculating the Jacobian is fairly simple and uses the formula already given in Equation 4.21. The computation of the Jacobian velocity is parallelized one velocity grid cell per thread and outputs the Jacobian matrix for each cell to be used by the next part.

The more important part of this step is the stretching (change) of the vorticity using the stress formula, referred to previously as the stress term in Equation 4.19 and subsequently elaborated as the matrix of all partial derivatives of the velocity (the Jacobian) in Equation 4.21. Once the Jacobian matrix of the velocity has been calculated, the velocity due to vorticity kernel is executed parallelized at one thread per particle, taking the Jacobian matrix as an input. An

Algorithm 6In-depth velocity calculation due to particle vorticity for velocity grid

Given output array U ofccell velocities

Given array P ofnparticle positions

Given array V ofnparticle vorticities

Given arrays F and L of sorted particle indices (First and Last) Given vorton influence radius R

Given spatial grid values - minimum (origin) O, cell size S //Spatial grid arrays have already been sorted

//Cell position is a function of its own index number //Cell world position is a function of spatial grid values

foreach grid cell in PARALLEL, with thread indexido

Cell C = cellfunc(i)

Cell world position W = wFunc(C, O, S)

//Find neighbours. Neighbouring cells are -1 to +1 in all directions for all-1x+1, -1y+1, -1z+1do

Neighbour N = C + Vec(x, y, z)

//If neighbour outside boundary, ignore

//Otherwise, obtain list of neighbouring particle ids in F and L

ifinsideBoundary(N)then

cell index= cellfunc(N)

f= F[cell index];l= L[cell index]

//Apply velocity due to vorticity for all neighbouring particles forp=f;p≤l;p++do

U[i] += velFromVort(P[p], V[p]/2, W, R) end for

end if end for

New cell velocity has been calculated. This is passed to the next step. end for

overview of the stretching step is shown in Algorithm 7. It involves calculating the velocity grid cell based on the particle position which is fairly standard, as well as the cell’s world position. These two positions are used to calculate the spacing during linear interpolation. Next, a linear interpolation of the given Jacobian matrices is performed, finding the final interpolated matrix

lerpJ. This matrix is used to transform the vorticity vector into the newstretchedvorticity. This is multiplied by the given timestep to arrive at the final vorticity.

The next step in the algorithm is the diffusion of vorticity - basically, nearby vortons share vorticity amongst themselves. This step follows the implementation of the viscous term of the Navier-stokes equations - it applies the fluid viscosity to the diffusion of the vortices as described earlier in Equation 4.22. There are two possible ways to go about this. Firstly, the vorticity can be diffused globally throughout the entire fluid. This means every vorton shares its vorticity with every other vorton - there is clearly a problem with this method however, as it does not scale well to larger system sizes.

A better method is to diffuse vorticity only in the local area. Because the amount of vorticity diffused is dependent on how close the vortons are to each other, a cutoff distance can be

SECTION 6.4: VELOCITY-VORTEX FIRE IMPLEMENTATION 105 / / C a l c u l a t e c e l l v e l o c i t y due t o v o r t o n v o r t i c i t y d e v i c e f l o a t 3 v e l f r o m v o r t (f l o a t 3 c e l l p o s , f l o a t 3 v o r t o n p o s , f l o a t 3 a n g v e l , f l o a t r a d i u s ){ f l o a t 3 r e l p o s = c e l l p o s v o r t o n p o s ; f l o a t d i s t = l e n g t h ( r e l p o s ) ; f l o a t r a d i u s s q = r a d i u s r a d i u s ; f l o a t d i s t s q = d i s t d i s t ; f l o a t e f f e c t i v e d i s t = 0 . 0 f ; / / H a n d l e c a s e where v o r t o n i s v e r y c l o s e t o c e l l p o s / / i . e make s u r e i t d o e s n ’ t i n d u c e a huge v e l o c i t y ( s i n g u l a r i t y ) i f( d i s t s q < r a d i u s s q ) / / i n s i d e v o r t o n e f f e c t i v e d i s t = 1 . 0 f / ( r a d i u s r a d i u s s q ) ; e l s e / / o u t s i d e v o r t o n e f f e c t i v e d i s t = 1 . 0 f / ( d i s t d i s t s q ) ; / / C r o s s p r o d u c t w x r f l o a t 3 cp = m a k e f l o a t 3 ( a n g v e l . y r e l p o s . z a n g v e l . z r e l p o s . y , a n g v e l . z r e l p o s . x a n g v e l . x r e l p o s . z , a n g v e l . x r e l p o s . y a n g v e l . y r e l p o s . x ) ; / / (w x r ) / ( 4 P i r ˆ 3 ) r e t u r n ( 1 . 0 f / FOURPI ) cp e f f e c t i v e d i s t ; }

Listing 6.6: Calculating the velocity of a grid cell due to vorton vorticity, using Biot-Savart’s law in relation to the angular velocity of a vorton. Notice here that an extra step has been taken to limit the velocity induced when the cell position is inside the vortex radius. In this case it restricts the effective distance r to the vortex radius, rather than the actual distance between the two points.

set whereby it is assumed that the amount of vorticity diffused is so small that it is ignored completely. Over several iterations this vorticity will propagate through the fluid as vortons continue to move around. As mentioned earlier, this method is known as the Particle Strength Exchange (PSE) method [140]. The local vorticity diffusion method is much more preferable in this case for larger system sizes and it can easily take advantage of the spatial indexing already provided by the spatial grid (velocity grid).

The diffusion step looks very similar to the velocity from vorticity step. Firstly, the cell ID is calculated based on the vorton position and the list of neighbouring cells are calculated based on this cell’s position in the grid. Then, for each of these neighbours, indices into the first and last sorted arrays are calculated to obtain a list of all vortons with which the current vorton will diffuse its vorticity.

Similar to the velocity from vorticity step, each neighbouring cell is checked to see whether it is outside the boundary of the velocity grid - if so, it is ignored and no vorticity is diffused to that cell. Otherwise, diffusion occurs for each pair of vortons by multiplying the viscosity of the fluid by the difference in vorticity of the two vortons in question.

Since this is happening all in parallel, the amount of vorticity diffused per vorton is doubled - this handles outgoing vorticity from the current vorton and incoming vorticity from the partner

Algorithm 7In-depth vorticity due to cell velocity algorithm for vortons. Given array V ofnparticle vorticities

Given array X ofnparticle positions

Given array J ofcJacobian matrices for cell velocity

Given the advection timestept

Given spatial grid values - minimum (origin) O, cell size S //Spatial grid arrays have already been sorted

//Cell position is a function of particle position

//Cell world position is a function of spatial grid values

foreach particle in PARALLEL, with thread indexido

Cell C = func(X[i])

Cell world position W = wFunc(C, O, S)

//Perform a trilinear interpolation over the surrounding Jacobians //Let each corner be considered a ”neighbour”

Given Neighbours N[8]

for allain 8 corners of the cell cubedo

Corner = Vec(x, y, z) where x, y, z are positive 0 or 1

N[a] = C + Corner

end for

Mat3 lerpJ = Lerp(X[i], W, N, J)

//Given lerpJ, find dot product of angular velocity Vec3 stretch = V[i] * lerpJ

V[i] = stretch *t

end for

New particle vorticity has been calculated. This is used in the next step. Algorithm 8Algorithm for the diffusion of vorticity in the local space.

Given output array D of diffused vorticities

Given array N of neighbouring vortons between F and L

Given array X ofnvorton positions

Given array V ofnvorton vorticities

Given mu, the fluid viscosity

Given the advection timestept

//Spatial grid arrays have already been sorted //Cell position is a function of particle position

foreach vorton in PARALLEL, with thread indexido

D[i] = V[i]

Cell C = func(X[i])

//Diffuse between all neighbouring vortons for allain Ndo

Vec3 vortdiff = V[i] - V[a]

Vec3 shared = vortdiff * mu *t

//Apply cutoff radius

ifX[i] - X[a]<cutoff radiusthen D[i] -= shared * 2

end if end for end for

SECTION 6.4: VELOCITY-VORTEX FIRE IMPLEMENTATION 107

Algorithm 9Buoy fire particles so they rise upwards

Given array U ofnvorton velocities

Given desired velocity B Given buoy co-efficient C

//For each vorton, make it move towards the desired velocity

foreach vorton in PARALLEL, with thread indexido

Vec3 veldiff = B - U[i] Vec3 buoy = C * veldiff U[i] += buoy

end for

vorton (outgoing vorticity is subtractive, while incoming vorticity is additive). Algorithm 8 gives a brief overview of this method.