//Basic first order semi-Lagrangian advection of velocities void FluidSim::advect(float dt) { temp_u.assign(0); temp_v.assign(0); temp_w.assign(0); //semi-Lagrangian advection on u-component of velocity for(int k = 0; k < nk; ++k) for(int j = 0; j < nj; ++j) for(int i = 0; i < ni+1; ++i) { Vec3f pos(i*dx, (j+0.5f)*dx, (k+0.5f)*dx); pos = trace_rk2(pos, -dt); temp_u(i,j,k) = get_velocity(pos)[0]; } //semi-Lagrangian advection on v-component of velocity for(int k = 0; k < nk; ++k) for(int j = 0; j < nj+1; ++j) for(int i = 0; i < ni; ++i) { Vec3f pos((i+0.5f)*dx, j*dx, (k+0.5f)*dx); pos = trace_rk2(pos, -dt); temp_v(i,j,k) = get_velocity(pos)[1]; } //semi-Lagrangian advection on w-component of velocity for(int k = 0; k < nk+1; ++k) for(int j = 0; j < nj; ++j) for(int i = 0; i < ni; ++i) { Vec3f pos((i+0.5f)*dx, (j+0.5f)*dx, k*dx); pos = trace_rk2(pos, -dt); temp_w(i,j,k) = get_velocity(pos)[2]; } //move update velocities into u/v vectors u = temp_u; v = temp_v; w = temp_w; }
//Basic first order semi-Lagrangian advection of velocities void FluidSim::advect(float dt) { //semi-Lagrangian advection on u-component of velocity for(int j = 0; j < nj; ++j) for(int i = 0; i < ni+1; ++i) { Vec2f pos(i*dx, (j+0.5f)*dx); pos = trace_rk2(pos, -dt); temp_u(i,j) = get_velocity(pos)[0]; } //semi-Lagrangian advection on v-component of velocity for(int j = 0; j < nj+1; ++j) for(int i = 0; i < ni; ++i) { Vec2f pos((i+0.5f)*dx, j*dx); pos = trace_rk2(pos, -dt); temp_v(i,j) = get_velocity(pos)[1]; } //move update velocities into u/v vectors u = temp_u; v = temp_v; }
void FluidSim::advect_particles(float dt) { for(unsigned int p = 0; p < particles.size(); ++p) { particles[p] = trace_rk2(particles[p], dt); //check boundaries and project exterior particles back in float phi_val = interpolate_value(particles[p]/dx, nodal_solid_phi); if(phi_val < 0) { Vec3f grad; interpolate_gradient(grad, particles[p]/dx, nodal_solid_phi); if(mag(grad) > 0) normalize(grad); particles[p] -= phi_val * grad; } } }
//Perform 2nd order Runge Kutta to move the particles in the fluid void FluidSim::advect_particles(float dt) { for(unsigned int p = 0; p < particles.size(); ++p) { particles[p] = trace_rk2(particles[p], dt); //Particles can still occasionally leave the domain due to truncation errors, //interpolation error, or large timesteps, so we project them back in for good measure. //Try commenting this section out to see the degree of accumulated error. float phi_value = interpolate_value(particles[p]/dx, nodal_solid_phi); if(phi_value < 0) { Vec2f normal; interpolate_gradient(normal, particles[p]/dx, nodal_solid_phi); normalize(normal); particles[p] -= phi_value*normal; } } }