//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) {
      Vec2f before = particles[p];
      Vec2f start_velocity = get_velocity(before);
      Vec2f midpoint = before + 0.5f*dt*start_velocity;
      Vec2f mid_velocity = get_velocity(midpoint);
      particles[p] += dt*mid_velocity;
      Vec2f after = particles[p];
      if(dist(before,after) > 3*dx) {
         std::cout << "Before: " << before << " " << "After: " << after << std::endl;
         std::cout << "Mid point: " << midpoint << std::endl;
         std::cout << "Start velocity: " << start_velocity << "  Time step: " << dt << std::endl;
         std::cout << "Mid velocity: " << mid_velocity << std::endl;
      }

      //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;
      }
   }

}
Exemple #2
0
float interpolate_normal(Vec3f& normal, const Vec3f& point, const Array3f& grid, const Vec3f& origin, const float dx) {
   float inv_dx = 1/dx;
   Vec3f temp = (point-origin)*inv_dx;
   float value = interpolate_gradient(normal, temp, grid);
   if(mag(normal) != 0)
      normalize(normal);
   return value;
}
//For extrapolated points, replace the normal component
//of velocity with the object velocity (in this case zero).
void FluidSim::constrain_velocity() {
   temp_u = u;
   temp_v = v;
   
   //(At lower grid resolutions, the normal estimate from the signed
   //distance function is poor, so it doesn't work quite as well.
   //An exact normal would do better.)
   
   //constrain u
   for(int j = 0; j < u.nj; ++j) for(int i = 0; i < u.ni; ++i) {
      if(u_weights(i,j) == 0) {
         //apply constraint
         Vec2f pos(i*dx, (j+0.5f)*dx);
         Vec2f vel = get_velocity(pos);
         Vec2f normal(0,0);
         interpolate_gradient(normal, pos/dx, nodal_solid_phi); 
         normalize(normal);
         float perp_component = dot(vel, normal);
         vel -= perp_component*normal;
         temp_u(i,j) = vel[0];
      }
   }
   
   //constrain v
   for(int j = 0; j < v.nj; ++j) for(int i = 0; i < v.ni; ++i) {
      if(v_weights(i,j) == 0) {
         //apply constraint
         Vec2f pos((i+0.5f)*dx, j*dx);
         Vec2f vel = get_velocity(pos);
         Vec2f normal(0,0);
         interpolate_gradient(normal, pos/dx, nodal_solid_phi); 
         normalize(normal);
         float perp_component = dot(vel, normal);
         vel -= perp_component*normal;
         temp_v(i,j) = vel[1];
      }
   }
   
   //update
   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;
      }
   }

}
void MarchingTriangles::eval_gradient( float y, float z, Vec2f& g )
{
   interpolate_gradient( g, Vec2f(y,z), phi );
}