/** \brief Lê o arquivo de parametrização dos custos de instrução O arquivo possui o formato de uma dupla de CODIGO_DE_OPERACAO e VALOR por linha e separados por espaços em branco. \param filename O caminho e nome para o arquivo de custos */ void read_costs (std::string filename) { std::ifstream myfile (filename); if (myfile.is_open()) { int latency, line_count=0; std::string opcode, line; while ( getline (myfile,line) ) { line_count++; std::stringstream stream(line); try { stream >> opcode >> latency; Operation::set_latency(Operation::string_to_opcode(opcode), latency); } catch (const std::out_of_range& oor) { std::stringstream ss; ss << "Erro lendo arquivo " << filename << " na linha " << line_count << ": " << line << std::endl; throw SimulationError(ss.str()); } } myfile.close(); } else {
void Simulation::addParticle(double x, double y, double vx, double vy, double radius, int mass, int r, int g, int b) { Particle *new_p = new Particle(x, y, vx, vy, radius, mass, width, height, r, g, b); // ensure that new particle does not overlap // with existing ones before adding it to the // simulation. for (Particle *p : particles) { if (new_p->overlaps(*p)) { std::ostringstream oss; oss << "Particle " << *new_p << " overlaps with " << "existing particle " << *p; throw SimulationError(oss.str()); } } particles.push_back(new_p); }
Simulation::Simulation(int width, int height, int fps) { this->width = width; this->height = height; this->fps = fps; is_paused = false; speed = SPEED_MIN; now = 0.0; delay_ms = 1000 / fps; window = nullptr; renderer = nullptr; if (SDL_CreateWindowAndRenderer(width, height, 0, &window, &renderer) != 0) { std::ostringstream oss; oss << "Failed to create window (SDL: " << SDL_GetError() << ")"; throw SimulationError(oss.str()); } resetBackgroundColor(); }
void Simulation::tick() { // The idea behind event driven simulation is quite // ingenious: we determine the time of all collisions // happening between all particles and walls assuming // that particles move by straight lines at constant // speed without any resistance. // // We keep the collision events arranged by time in priority // queue, so that we always know when and what collisions // are going to happen. // // The expensive calculations have to be done only // once when the priority queue is initialised. By the expensive // calculations I mean the calculation of all collisions between // all available particles O(n^2). Then the event driven model // requires to recalculate new events only after some event (collision) // happens, which requires no more than O(N). That's why this // model is so swift. // // Of course some of the events in the queue have to be cancelled after // the collision event happens (since particle's trajectories change), // that's why the system allows to detect whether the event // is stale/cancelled. if (events.empty()) { if (particles.size() == 0) { throw SimulationError("Simulation can not be launched " "with 0 particles"); } initializeEvents(); } if (is_paused) { SDL_Delay(delay_ms); return; } bool enough = false; while (!enough) { Event *ev = events.top(); events.pop(); if (ev->isStale()) { delete ev; continue; } // simulation system does time related calculations // in relative time, not absolute. So we have to // translate relative time time to absolute one // and vice versa. moveParticles(ev->getTime() - now); SDL_Delay(simulationTimeToMS(ev->getTime() - now)); now = ev->getTime(); switch (ev->getType()) { case EventType::WallCollision: { // Particle collides a wall. This requires to calculate // the collisions of this particle with all other particles // and walls. WallCollisionEvent *wc_ev = dynamic_cast<WallCollisionEvent*>(ev); wc_ev->getParticle().bounceWall(wc_ev->getWallType()); predictCollisions(wc_ev->getParticle()); break; } case EventType::ParticleCollision: { // Two particles collide each other. This requires to calculate // the collisions of these two particles with all other particles // and walls. ParticleCollisionEvent *pc_ev = dynamic_cast<ParticleCollisionEvent*>(ev); pc_ev->getFirstParticle().bounceParticle(pc_ev->getSecondParticle()); predictCollisions(pc_ev->getFirstParticle()); predictCollisions(pc_ev->getSecondParticle()); break; } case EventType::Refresh: refresh(); enough = true; events.push(new RefreshEvent(now + MSToSimulationTime(delay_ms))); break; } delete ev; } }
void nest::SimulationManager::resume_( size_t num_active_nodes ) { assert( kernel().is_initialized() ); std::ostringstream os; double_t t_sim = to_do_ * Time::get_resolution().get_ms(); os << "Number of local nodes: " << num_active_nodes << std::endl; os << "Simulaton time (ms): " << t_sim; #ifdef _OPENMP os << std::endl << "Number of OpenMP threads: " << kernel().vp_manager.get_num_threads(); #else os << std::endl << "Not using OpenMP"; #endif #ifdef HAVE_MPI os << std::endl << "Number of MPI processes: " << kernel().mpi_manager.get_num_processes(); #else os << std::endl << "Not using MPI"; #endif LOG( M_INFO, "SimulationManager::resume", os.str() ); terminate_ = false; if ( to_do_ == 0 ) return; if ( print_time_ ) { // TODO: Remove direct output std::cout << std::endl; print_progress_(); } simulating_ = true; simulated_ = true; update_(); simulating_ = false; if ( print_time_ ) std::cout << std::endl; kernel().mpi_manager.synchronize(); if ( terminate_ ) { LOG( M_ERROR, "SimulationManager::resume", "Exiting on error or user signal." ); LOG( M_ERROR, "SimulationManager::resume", "SimulationManager: Use 'ResumeSimulation' to resume." ); if ( SLIsignalflag != 0 ) { SystemSignal signal( SLIsignalflag ); SLIsignalflag = 0; throw signal; } else throw SimulationError(); } LOG( M_INFO, "SimulationManager::resume", "Simulation finished." ); }