void System<DataType,Integrator,Potential,Communicator>::simulate(int numIters, std::ostream & output) { // MPI Comms. // clearBuffers() ; appendTransitionsToBuffers() ; appendInteractionsToBuffers() ; communicateInteractionsTransitions() ; // Initialise the forces. // updateForces() ; // Prime the velocity based on the integration policy. // for (unsigned int i = 0 ; i < positions.size() ; i+=2) { Integrator::initialise(&positions[i], &velocities[i], &forces[i]) ; } // Update velocities and positions based on the integration policy. // for (int i = 0; i < numIters ; ++i) { updateVelocities() ; updatePositions() ; // MPI Comms. clearBuffers() ; appendTransitionsToBuffers() ; appendInteractionsToBuffers() ; communicateInteractionsTransitions() ; updateForces() ; printSystem(output,i) ; output << std::endl << std::endl ; } } /* ----- end of member function simulate ----- */
static void updateForces(int firstStar, int secondStar, struct star* star_array) { if (firstStar > 0){ if (secondStar > 1){ addForce(&star_array[firstStar],&star_array[secondStar]); updateForces(firstStar, secondStar - 1, star_array); }else{ updateForces(firstStar - 1, firstStar - 2, star_array); } } }
// Update is called every frame or as specified in the max desired updates per // second GUI slider void FluidSimulation3D::update() { SCOPE_CYCLE_COUNTER(STAT_AtmosphericsUpdate) updateDiffusion(); updateForces(); updateAdvection(); }
void particleSystem::advance(float timestep){ dt = timestep; // For each particles i ... #pragma omp parallel for for(int i=0; i < particles.size(); ++i) { // Normal verlet stuff particles[i].pos_old = particles[i].pos; particles[i].pos += particles[i].vel * dt; // Apply the currently accumulated forces particles[i].pos += particles[i].force * dt * dt; // Restart the forces with gravity only. We'll add the rest later. particles[i].force = globalForce; // Calculate the velocity for later. particles[i].vel = (particles[i].pos - particles[i].pos_old)/dt; // If the velocity is really high, we're going to cheat and cap it. // This will not damp all motion. It's not physically-based at all. Just // a little bit of a hack. float max_vel = 2.f; float vel_mag = particles[i].vel.len2(); // If the velocity is greater than the max velocity, then cut it in half. if(vel_mag > max_vel*max_vel) particles[i].vel = particles[i].vel * .5f; // If the particle is outside the bounds of the world, then // Make a little spring force to push it back in. if(particles[i].pos.x < -simW) particles[i].force.x -= (particles[i].pos.x - -simW) / 8; if(particles[i].pos.x > simW) particles[i].force.x -= (particles[i].pos.x - simW) / 8; if(particles[i].pos.y < bottom) particles[i].force.y -= (particles[i].pos.y - bottom) / 8; if(particles[i].pos.y > simW*2) particles[i].force.y -= (particles[i].pos.y - simW*2) / 8; // Handle the mouse attractor. // It's a simple spring based attraction to where the mouse is. // float attr_dist2 = (particles[i].pos - attractor).len2(); //const float attr_l = simW/4; //if( attracting ) // if( attr_dist2 < attr_l*attr_l ) // particles[i].force -= (particles[i].pos - attractor) / 256; // Reset the nessecary items. particles[i].rho = particles[i].rho_near = 0; particles[i].neighbors.clear(); } updateForces(); if (kill) { for (int i = particles.size()-1; i >= 0; i--) { particles[i].lifetime -= dt; if (particles[i].lifetime < 0.0) eraseParticle(i); } } }
int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QMainWindow::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: setIso(); break; case 1: launchApp(); break; case 2: updateForces(); break; case 3: deleteCells(); break; case 4: clearQGview(); break; case 5: redrawQGview(); break; case 6: selectContainer((*reinterpret_cast< int(*)>(_a[1]))); break; default: ; } _id -= 7; } return _id; }
void SPH::timestep(float dt) { if(_nActive < _nParticles && _tStep%5 == 0) { ++_nActive; } // Update Time counters _dt = dt; _T += _dt; ++_tStep; // Update Parameters updateDensityPressure(); updateForces(); _vmax = 0; for(unsigned i=0; i<_nActive; ++i) { // Update Velocities _v1[i] += _dt*_a1[i]; _v2[i] += _dt*_a2[i]; _v3[i] += _dt*_a3[i]; _vmax = std::max(std::max(_vmax,std::abs(_v1[i])),std::max(std::abs(_v2[i]),std::abs(_v3[i]))); // Update Positions _x1[i] += _dt*_v1[i]; _x2[i] += _dt*_v2[i]; _x3[i] += _dt*_v3[i]; } /* unsigned microseconds = 20000; usleep(microseconds); */ }
void ParticleField::Update() { updateForces(); updateParticles(); killParticles(); spawnParticles(); }
// Runge Kutta 4th Order simulation step - WORK IN PROGRESS, fails on multiple collisions void Sim::rungeKuttaStep(float dt) { vec3 x,v, dx1, dx2, dx3, dx4, dv1, dv2, dv3, dv4; int i,j; // Step 1 updateForces(0); for(i=0; i<myFlag->particlesHigh; i++) { for(j=0; j<myFlag->particlesWide; j++) { // pin the corners and detect collisions if(myFlag->particles[i][j]->pinned || myPerson->collidesWith(myFlag->particles[i][j]) || myGround->collidesWith(myFlag->particles[i][j])) { // set velocity to zero myFlag->particles[i][j]->velocity=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity1=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity2=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity3=vec3(0.0f,0.0f,0.0f); continue; // skip euler for this particle } // update all other particles else { // capture current position and velocity x = myFlag->particles[i][j]->position; v = myFlag->particles[i][j]->velocity; // calculate RK4 values dx1 = dt * v; dv1 = dt * myFlag->particles[i][j]->force; //acceleration(x,T); // store intermediate values myFlag->particles[i][j]->position1 = x + dx1/2.0f; myFlag->particles[i][j]->velocity1 = v + dv1/2.0f; } } } // Step 2 updateForces(1); for(i=0; i<myFlag->particlesHigh; i++) { for(j=0; j<myFlag->particlesWide; j++) { // pin the corners and check for collisions if(myFlag->particles[i][j]->pinned || myPerson->collidesWith(myFlag->particles[i][j]) || myGround->collidesWith(myFlag->particles[i][j])) { // set velocity to zero myFlag->particles[i][j]->velocity=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity1=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity2=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity3=vec3(0.0f,0.0f,0.0f); continue; // skip euler for this particle } // update all other particles else { // capture current position and velocity x = myFlag->particles[i][j]->position; v = myFlag->particles[i][j]->velocity; // calculate RK4 values dx2 = dt * (v + dv1/2.0f); dv2 = dt * myFlag->particles[i][j]->force; //acceleration(x + dx1/2.0f, T + dt/2.0f); // store intermediate values myFlag->particles[i][j]->position2 = x + dx2/2.0f; myFlag->particles[i][j]->velocity2 = v + dv2/2.0f; } } } // Step 3 updateForces(2); for(i=0; i<myFlag->particlesHigh; i++) { for(j=0; j<myFlag->particlesWide; j++) { // pin the corners and check for collisions if(myFlag->particles[i][j]->pinned || myPerson->collidesWith(myFlag->particles[i][j]) || myGround->collidesWith(myFlag->particles[i][j])) { // set velocity to zero myFlag->particles[i][j]->velocity=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity1=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity2=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity3=vec3(0.0f,0.0f,0.0f); continue; // skip euler for this particle } // update all other particles else { // capture current position and velocity x = myFlag->particles[i][j]->position; v = myFlag->particles[i][j]->velocity; // calculate RK4 values dx3 = dt * (v + dv2/2.0f); dv3 = dt * myFlag->particles[i][j]->force; //acceleration(x + dx2/2.0f, T + dt/2.0f); // store intermediate values myFlag->particles[i][j]->position3 = x + dx3; myFlag->particles[i][j]->velocity3 = v + dv3; } } } // Step 4 updateForces(3); for(i=0; i<myFlag->particlesHigh; i++) { for(j=0; j<myFlag->particlesWide; j++) { // pin the corners and check for collisions if(myFlag->particles[i][j]->pinned || myPerson->collidesWith(myFlag->particles[i][j]) || myGround->collidesWith(myFlag->particles[i][j])) { // set velocity to zero myFlag->particles[i][j]->velocity=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity1=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity2=vec3(0.0f,0.0f,0.0f); myFlag->particles[i][j]->velocity3=vec3(0.0f,0.0f,0.0f); continue; // skip euler for this particle } // update all other particles else { // capture current position and velocity x = myFlag->particles[i][j]->position; v = myFlag->particles[i][j]->velocity; // calculate RK4 values dx4 = dt * (v + dv3); dv4 = dt * myFlag->particles[i][j]->force; // acceleration(x + dx3, T + dt); // update final positions and velocities myFlag->particles[i][j]->position = x + dx1/6.0f + dx2/3.0f + dx3/3.0f + dx4/6.0f; myFlag->particles[i][j]->velocity = v + dv1/6.0f + dv2/3.0f + dv3/3.0f + dv4/6.0f; } } } }
// Semi-Implicit Euler simulation step void Sim::semiImplicitEuler(float dt) { int i,j; vec3 x,v,a,x_prime,v_prime,a_prime; Particle *p; // Check if user moved character if(personMoved) { for( i=0; i<myFlag->particlesHigh; i++ ) { for( j=0; j<myFlag->particlesWide; j++ ) { if(myPerson->collidesWith(myFlag->particles[i][j])) { myFlag->particles[i][j]->position += (directionMoved * stepSize); } } } // reset flag personMoved = false; } // get values for current x,v,a updateForces(0); for(i=0; i<myFlag->particlesHigh; i++) { for(j=0; j<myFlag->particlesWide; j++) { p = myFlag->particles[i][j]; // for the particle secured to the top of the penguin's body if(p->pinned) { p->position = myPerson->body->origin - vec3(0.0f,myPerson->body->radius,0.0f); continue; } else if(myPerson->collidesWith(p)) { // move particle to outside the person if(p->position.y >= myPerson->head->origin.y + myPerson->head->radius) { // bump to outside the body p->position = myPerson->body->origin + (normalize(p->position - myPerson->body->origin) * myPerson->body->radius * 1.1f); } else { // bump to outside head p->position = myPerson->head->origin + (normalize(p->position - myPerson->head->origin) * myPerson->head->radius * 1.1f); } continue; // adjust for collision with ground } else if(myGround->collidesWith(myFlag->particles[i][j])){ continue; // update all other particles } else { // values at current time x = p->position_old; v = p->velocity_old; a = p->acceleration_old; // euler to approximate future values v_prime = v + dt * a; x_prime = x + dt * v_prime; a_prime = p->acceleration; // use approx future values to find s.e.i. result v = v + dt * a_prime; p->velocity = v; p->position += v*dt; p->acceleration = a_prime; p->position1 = x_prime; p->velocity1 = v_prime; } } } }
// Euler simulation step void Sim::eulerStep(float dt) { int i,j; vec3 x, v, a; if(personMoved) { for( i=0; i<myFlag->particlesHigh; i++ ) { for( j=0; j<myFlag->particlesWide; j++ ) { if(myPerson->collidesWith(myFlag->particles[i][j])) { myFlag->particles[i][j]->position += (directionMoved * stepSize); myFlag->particles[i][j]->pinned = true; } else { myFlag->particles[i][j]->pinned = false; } } } // reset flag personMoved = false; } // update forces on particles updateForces(0); // update velocities and positions of particles for( i=0; i<myFlag->particlesHigh; i++ ) { for( j=0; j<myFlag->particlesWide; j++ ) { if(myPerson->collidesWith(myFlag->particles[i][j])){ // move particle to outside the person if(myFlag->particles[i][j]->position.y >= myPerson->head->origin.y + myPerson->head->radius) { // bump to outside the body myFlag->particles[i][j]->position = myPerson->body->origin + (normalize(myFlag->particles[i][j]->position - myPerson->body->origin) * myPerson->body->radius * 1.1f); } else { // bump to outside head myFlag->particles[i][j]->position = myPerson->head->origin + (normalize(myFlag->particles[i][j]->position - myPerson->head->origin) * myPerson->head->radius * 1.1f); } continue; // adjust for collision with ground } else if(myGround->collidesWith(myFlag->particles[i][j])){ continue; // update all other particles } else { // calculate acceleration: a = F/m where m=1 a = myFlag->particles[i][j]->force; // get velocity of spring v = myFlag->particles[i][j]->velocity; // update velocity v = v + dt*a; myFlag->particles[i][j]->velocity = v; // get position of spring x = myFlag->particles[i][j]->position; // update position x = x + v*dt;// + 0.5f * a * dt * dt; myFlag->particles[i][j]->position = x; // ignore very small velocities if(length(v) <= EPSILON) { myFlag->particles[i][j]->velocity = vec3(0.0f,0.0f,0.0f); } } } } }
// ------- update void wave::update(vector<inputManager::Target> &targets){ updateForces(targets); updatePolyline(); }
SPH::SPH(unsigned N) : _nParticles(N), _nGhostObject(_uicSize), _x1BoxDim(0), // keep it 2d _x2BoxDim(280), _x3BoxDim(100), _nGhostWall(2*(_x2BoxDim+1+_x3BoxDim+1)*_ghostDepth), // keep it 2d _nTotal(_nParticles+_nGhostObject+_nGhostWall), _nActive(0), _x1(new float[_nTotal]), _x2(new float[_nTotal]), _x3(new float[_nTotal]), _v1(new float[_nTotal]), _v2(new float[_nTotal]), _v3(new float[_nTotal]), _a1(new float[_nTotal]), _a2(new float[_nTotal]), _a3(new float[_nTotal]), _m(new float[_nTotal]), _rho(new float[_nTotal]), _p(new float[_nTotal]), _r(new float[_nTotal]), _vmax(1e-10), _g(0), _damping(.8), _support(10), _h(.5*_support), _kPressure(1), _rho0(1), _mu(0), _T(0.0), _tStep(0), _dt(0), _boxMoved(false) { if(_x1BoxDim%2 || _x2BoxDim%2 || _x3BoxDim%2) { std::cout << "Error: please select even dimension for box"; throw -1; } std::cout << "\nInitializing Model..."; initObjectCoords(); // Seeding random number generator and set parameters for normal distribution // std::random_device rd; // Uncomment to make it even more random ;) // std::mt19937 e2(rd()); std::mt19937 e2(42); float mean = 50; // mean velocity float stddev = 10; // standard deviation of velocity std::normal_distribution<> dist(mean,stddev); // Initialize Fluid Particles for(unsigned i=0; i<_nParticles; ++i) { // Position (Locate at source) _x1[i] = 0; // keep it 2d _x2[i] = -.45*_x2BoxDim; // fmod(rand(),_x2BoxDim)-.5*_x2BoxDim; _x3[i] = .45*_x3BoxDim; // fmod(rand(),_x3BoxDim)-.5*_x3BoxDim; // Masses (assume two groups of particle masses) _m[i] = .5*(1+i%2); _rho[i] = 1; _p[i] = 1; // Radius / Support of particles _r[i] = 1; // 1+i%3; // Compute Forces acting on particles based on positions updateForces(); // Velocities (sampled from random normal distribution) _v1[i] = 0; // keep it 2d _v2[i] = dist(e2); _v3[i] = 0; // dist(e2); } // Initialize Ghost Particles in Object for(unsigned i=_nParticles; i<(_nParticles+_nGhostObject); ++i) { unsigned objectIndex = i - _nParticles; _x1[i] = _uic[0][objectIndex]; _x2[i] = _uic[1][objectIndex]; _x3[i] = _uic[2][objectIndex]; _v1[i] = 0; _v2[i] = 0; _v3[i] = 0; _r[i] = 1; _m[i] = 1; _p[i] = 1; } // Initialize Ghost Particles in Wall // temporary indices for loop unsigned zeroIndex; for(unsigned d=0; d<_ghostDepth; ++d) { zeroIndex = _nParticles + _nGhostObject + 2*d*(_x2BoxDim+1+_x3BoxDim+1); for(unsigned i=0; i<(2*_x3BoxDim+1); ++i) { _x1[zeroIndex+i] = 0; // keep it 2d _x2[zeroIndex+i] = (i%2 ? 1 : -1) * (.5*_x2BoxDim + d); // place on alternating sides _x3[zeroIndex+i] = -.5*_x3BoxDim + i/2; // place at distance 1 apart // v=0 for wall particles _v1[zeroIndex+i] = 0; _v2[zeroIndex+i] = 0; _v3[zeroIndex+i] = 0; _m[zeroIndex+i] = 1e3; _p[zeroIndex+i] = 1; _r[zeroIndex+i] = .4; } zeroIndex += 2*_x3BoxDim; for(unsigned i=0; i<(2*_x2BoxDim+1); ++i) { _x1[zeroIndex+i] = 0; // keep it 2d _x2[zeroIndex+i] = -.5*_x2BoxDim + i/2; // place at distance 1 apart _x3[zeroIndex+i] = (i%2 ? 1 : -1) * (.5*_x3BoxDim + d); // place on alternating sides // v=0 for wall particles _v1[zeroIndex+i] = 0; _v2[zeroIndex+i] = 0; _v3[zeroIndex+i] = 0; _m[zeroIndex+i] = 1; _p[zeroIndex+i] = 1; _r[zeroIndex+i] = .4; } } }
int main(int argc, char* argv[]) { int number_of_stars = 200; int iterations = 1000; prec time_unit = gdt; if(argc == 3) { number_of_stars = atoi(argv[1]); iterations = atoi(argv[2]); } struct star* star_array = malloc(sizeof(struct star) * number_of_stars); generate_init_values(number_of_stars, star_array); #ifdef ANIMATE XPoint* points = malloc(sizeof(XPoint)*number_of_stars); Display* disp; Window window, rootwin; int screen; disp = XOpenDisplay(NULL); screen = DefaultScreen(disp); rootwin = RootWindow(disp,screen); window = XCreateSimpleWindow(disp,rootwin, 0,0,X_SIZE,Y_SIZE,1,0,0); GC gc = XCreateGC(disp, window, 0, 0); XSetForeground(disp, gc, WhitePixel(disp, screen)); XSetBackground(disp, gc, BlackPixel(disp, screen)); XMapWindow(disp,window); XClearWindow(disp,window); copyToXBuffer(star_array, points, number_of_stars); XDrawPoints(disp, window, gc, points, number_of_stars, 0); XFlush(disp); #endif clock_t start = clock(); for(int i = 0; i < iterations; i++) { #ifndef ANIMATE resetForces(number_of_stars, star_array); updateForces(number_of_stars, number_of_stars - 1, star_array); for(int j = 0; j < number_of_stars; ++j){ update_position(&star_array[j], time_unit); } #endif #ifdef ANIMATE resetForces(number_of_stars, star_array); updateForces(number_of_stars, number_of_stars - 1, star_array); for(int j = 0; j < number_of_stars; ++j){ update_position(&star_array[j], time_unit); copyToXBuffer(star_array, points,number_of_stars ); XDrawPoints(disp, window, gc, points, number_of_stars, CoordModeOrigin); } XClearWindow(disp,window); #endif } clock_t stop = clock(); float diff = (float)(stop - start)/CLOCKS_PER_SEC; printf("Total: %lf seconds\n",diff); printf("Bodies: %d\n",number_of_stars); printf("Iterations: %d\n", iterations); #ifdef ANIMATE free(points); XCloseDisplay(disp); #endif free(star_array); return 0; }