Пример #1
0
 /* Simple forward Euler method for velocity integration in time */
 void euler(double &x, double &y, double timestep, const FluidQuantity &u, const FluidQuantity &v) const {
     double uVel = u.lerp(x, y)/_hx;
     double vVel = v.lerp(x, y)/_hx;
     
     x -= uVel*timestep;
     y -= vVel*timestep;
 }
Пример #2
0
 /* Builds the pressure right hand side as the negative divergence */
 void buildRhs() {
     double scale = 1.0/_hx;
     
     for (int y = 0, idx = 0; y < _h; y++) {
         for (int x = 0; x < _w; x++, idx++) {
             _r[idx] = -scale*(_u->at(x + 1, y) - _u->at(x, y) +
                               _v->at(x, y + 1) - _v->at(x, y));
         }
     }
 }
Пример #3
0
 double maxTimestep() {
     double maxVelocity = 0.0;
     for (int y = 0; y < _h; y++) {
         for (int x = 0; x < _w; x++) {
             double u = _u->lerp(x + 0.5, y + 0.5);
             double v = _v->lerp(x + 0.5, y + 0.5);
             
             double velocity = sqrt(u*u + v*v);
             maxVelocity = max(maxVelocity, velocity);
         }
     }
     
     double maxTimestep = 4.0*_hx/maxVelocity;
     
     return min(maxTimestep, 1.0);
 }
Пример #4
0
 /* Returns the maximum allowed timestep. Note that the actual timestep
  * taken should usually be much below this to ensure accurate
  * simulation - just never above.
  */
 double maxTimestep() {
     double maxVelocity = 0.0;
     for (int y = 0; y < _h; y++) {
         for (int x = 0; x < _w; x++) {
             /* Average velocity at grid cell center */
             double u = _u->lerp(x + 0.5, y + 0.5);
             double v = _v->lerp(x + 0.5, y + 0.5);
             
             double velocity = sqrt(u*u + v*v);
             maxVelocity = max(maxVelocity, velocity);
         }
     }
     
     /* Fluid should not flow more than two grid cells per iteration */
     double maxTimestep = 2.0*_hx/maxVelocity;
     
     /* Clamp to sensible maximum value in case of very small velocities */
     return min(maxTimestep, 1.0);
 }
Пример #5
0
 /* Convert fluid density to RGBA image */
 void toImage(unsigned char *rgba) {
     for (int i = 0; i < _w*_h; i++) {
         int shade = (int)((1.0 - _d->src()[i])*255.0);
         shade = max(min(shade, 255), 0);
         
         rgba[i*4 + 0] = shade;
         rgba[i*4 + 1] = shade;
         rgba[i*4 + 2] = shade;
         rgba[i*4 + 3] = 0xFF;
     }
 }
Пример #6
0
 void update(double timestep) {
     buildRhs();
     project(600, timestep);
     applyPressure(timestep);
     
     _d->advect(timestep, *_u, *_v);
     _u->advect(timestep, *_u, *_v);
     _v->advect(timestep, *_u, *_v);
     
     _d->flip();
     _u->flip();
     _v->flip();
 }
Пример #7
0
 void update(double timestep) {
     buildRhs();
     project(600, timestep);
     applyPressure(timestep);
     
     _d->advect(timestep, *_u, *_v);
     _u->advect(timestep, *_u, *_v);
     _v->advect(timestep, *_u, *_v);
     
     /* Make effect of advection visible, since it's not an in-place operation */
     _d->flip();
     _u->flip();
     _v->flip();
 }
Пример #8
0
 /* Applies the computed pressure to the velocity field */
 void applyPressure(double timestep) {
     double scale = timestep/(_density*_hx);
     
     for (int y = 0, idx = 0; y < _h; y++) {
         for (int x = 0; x < _w; x++, idx++) {
             _u->at(x,     y    ) -= scale*_p[idx];
             _u->at(x + 1, y    ) += scale*_p[idx];
             _v->at(x,     y    ) -= scale*_p[idx];
             _v->at(x,     y + 1) += scale*_p[idx];
         }
     }
     
     for (int y = 0; y < _h; y++)
         _u->at(0, y) = _u->at(_w, y) = 0.0;
     for (int x = 0; x < _w; x++)
         _v->at(x, 0) = _v->at(x, _h) = 0.0;
 }
Пример #9
0
    /* Third order Runge-Kutta for velocity integration in time */
    void rungeKutta3(double &x, double &y, double timestep, const FluidQuantity &u, const FluidQuantity &v) const {
        double firstU = u.lerp(x, y)/_hx;
        double firstV = v.lerp(x, y)/_hx;

        double midX = x - 0.5*timestep*firstU;
        double midY = y - 0.5*timestep*firstV;

        double midU = u.lerp(midX, midY)/_hx;
        double midV = v.lerp(midX, midY)/_hx;

        double lastX = x - 0.75*timestep*midU;
        double lastY = y - 0.75*timestep*midV;

        double lastU = u.lerp(lastX, lastY);
        double lastV = v.lerp(lastX, lastY);
        
        x -= timestep*((2.0/9.0)*firstU + (3.0/9.0)*midU + (4.0/9.0)*lastU);
        y -= timestep*((2.0/9.0)*firstV + (3.0/9.0)*midV + (4.0/9.0)*lastV);
    }
Пример #10
0
 /* Set density and x/y velocity in given rectangle to d/u/v, respectively */
 void addInflow(double x, double y, double w, double h, double d, double u, double v) {
     _d->addInflow(x, y, x + w, y + h, d);
     _u->addInflow(x, y, x + w, y + h, u);
     _v->addInflow(x, y, x + w, y + h, v);
 }