void graphics_show_cairo_surface(void *data, Environment *environment) { if (environment -> fast_run) {return;} cairo_surface_t *surface = (cairo_surface_t *) data; cairo_set_source_surface(environment -> cairo, surface, 0, 0); profiler_start(profile_cairo); cairo_paint(environment -> cairo); profiler_end(profile_cairo); }
// --------------------------------------------------------------------------- /// Performs time step for the particles and starts parallel exchange. // --------------------------------------------------------------------------- void plasma_move (meshVec_RO_p E, meshVec_RO_p H, meshVec_p J) { profiler_begin (mc_prof_plasma_cleanJ); plasma_J = J; mf_mesh_clean (plasma_J); plasmaWx = plasmaWy = plasmaWz = 0; #if defined(ACTIVATE_TRACER) && ACTIVATE_TRACER fwrite (&Time, sizeof(Time), 1, tracer); #endif // Remembers initial core size and makes shell timestep. long int unprocessedCore = countCore; plasma_timestep (DOING_SHELL, countShell, E, H, J); // Applies local boundary conditions. profiler_endBegin (mc_prof_plasma_pbcPop); for (int b = 0 ; b < 6 ; ++b) BC[b][cpu_bc_min[b]] (); // Sends outgoing particles. comm_plasma_send (); // Parallel exchange (particles and currents). profiler_endBegin (mc_prof_plasma_jbc); jbc_start (mcast_meshVec (plasma_J)); // Final timestep (unprocessed core particles). plasma_timestep (DOING_CORE, countAll - unprocessedCore, E, H, J); #if defined(ACTIVATE_TRACER) && ACTIVATE_TRACER marker_t p = {.id = 0}; fwrite (&p, sizeof(p), 1, tracer); #endif profiler_end (); } // --------------------------------------------------------------------------- /// Reports thermal energy of plasma. // --------------------------------------------------------------------------- void plasma_temperature (double *WTx, double *WTy, double *WTz) { *WTx = plasmaWx; *WTy = plasmaWy; *WTz = plasmaWz; }
void graphics_present(Environment *environment) { if (environment -> fast_run) {return;} profiler_start(profile_present); void *pixels; int pitch; SDL_Rect rect; rect.x = 0; rect.y = 0; rect.w = environment -> width; rect.h = environment -> height; cairo_surface_flush(environment -> cairo_surface); SDL_UnlockTexture(environment -> base_texture); SDL_RenderCopy(environment -> renderer, environment -> base_texture, &rect, &rect); SDL_RenderPresent(environment -> renderer); SDL_LockTexture(environment -> base_texture, NULL, &pixels, &pitch); profiler_end(profile_present); }
/** * Signals to profiler that simulation loop is finished. */ void profiler_finishLoop(void) { profiler_end(); // Closes main profiler interval. char empty1[60], empty2[60]; // Empty strings for output formatting. double invBlockTime[mc_maxLevel] = { 1 }; // Coefficients for percentage evaluation. memset(empty1, ' ', sizeof(char) * 60); // Prepares empty string to print indents. memset(empty2, ' ', sizeof(char) * 60); fprintf(profFile, "--------------- %d intervals ---------------\n", (int) (profEvent - profEvents)); sample_t *event = profEvents; for(; event < profEvent; ++event) { const int level = event->level; const nameBind_t *const name = profBinds + event->id; empty1[level * 2] = 0; // Sets length of the offset. empty2[profLongestName - name->nameLenght + 8 - 2 * level] = 0; // Sets span between to reach the next column. const double dt = event->accumulated; // Alias for time interval. invBlockTime[level] = 100.0 / (dt + 1e-10); // 100 to turn everything into percents. const int levelDn = (level > 0) ? level - 1 : 0; fprintf(profFile, "%s%s: %s%8.4f%% %.4e sec %8.4f%%\n", empty1, name->name, empty2, dt * invBlockTime[levelDn], dt, dt * invBlockTime[0]); empty1[level * 2] = ' '; // Restores prepared line for offset. empty2[profLongestName - name->nameLenght + 8 - 2 * level] = ' '; // Restores prepared line for column shift. event->accumulated = 0; // Prepares for next session. } #if defined (mc_debugChecks) && mc_debugChecks == 1 if(profLevel != -1) error("profiler_finishLoop: there are %d open blocks which are not closed properly.", profLevel + 1); #endif profEvent = profEvents; profLevel = -1; profAccumEvent = 0; }
// --------------------------------------------------------------------------- /// Mandor2 core. // --------------------------------------------------------------------------- int main (int argc, char **argv) { time_get (&stopFlag_startTime); cl_import ("./source/import.pl", argc, argv, 0); parameter_enterMPI (argc, argv, 1); parameter_load (); // Initializes profiler. profiler_init (_("output/prof_core_%03d.txt", cpu_here)); units_load (); // Configures all modules. main_startUp (); em_init (&E, &H); plasma_init (); for (int tmp = 0; tmp < 100; tmp++) tmp_gamma[tmp] = 0.0; // TEMP say ("System is initialized successfully."); // Total time of the work stage - starts here. int stopFlag = 0; double computTime = MPI_Wtime (), oldTime = -1; for (int t = 1 ; t <= totalSteps && !stopFlag ; t++) { double W_E, W_M, WTx = 0, WTy = 0, WTz = 0; profiler_startLoop (); // XXX Add it to the timing counter. comm_plasma_start (); // Reads data from external file (works as mailbox).. profiler_begin (mc_prof_throwStopFlag); if (chPoint_stopRequest > 0 && t%chPoint_stopRequest == 0) main_throwStopFlag (); // H^(n-1/2) -> H^n. profiler_endBegin (mc_prof_emh1); em_HHalfStep (mcast_meshVec_RO (&E), &H); // Energy density of the field at t = n*tau. profiler_endBegin (mc_prof_EMenergy); em_energy (mcast_meshVec_RO(&E), mcast_meshVec_RO(&H), &W_E, &W_M); profiler_endBegin (mc_prof_probes); probe_postData (Time, mcast_meshVec_RO(&E), mcast_meshVec_RO(&H)); // Gauss law test beginning (profiler call is inside). gauss_before (); profiler_endBegin (mc_prof_plasma_move); plasma_move (mcast_meshVec_RO(&E), mcast_meshVec_RO(&H), &J); // Energy density: gets plasma termal energy. profiler_endBegin (mc_prof_plasma_Txyz); plasma_temperature (&WTx, &WTy, &WTz); // Tecplot's diagnostic check-pointing. if (chPoint_tecplot > 0 && t%chPoint_tecplot == 0) { say_doing ("writing tecplot mesh..."); profiler_endBegin (mc_prof_tecRho); plasma_rho (&rho); profiler_endBegin (mc_prof_tecEH); tecIO_saveFields (Time, mcast_meshVec_RO(&E), mcast_meshVec_RO(&H)); } // Spectral energy density diagnostic. if (chPoint_spectr > 0 && t%chPoint_spectr == 0) { say_doing ("writing spectral energy density dump..."); profiler_endBegin (mc_prof_spectr); reg_t reg = {{cpu_min[0], cpu_min[1], cpu_min[2]}, {cpu_max[0] - mc_have_x, cpu_max[1] - mc_have_y, cpu_max[2] - mc_have_z}}; reg_t map = {{E.imin, E.jmin, E.kmin}, {E.imax, E.jmax, E.kmax}}; spectr_dump (Time, cpu_here, cpu_total, ®, &map, E.storage, H.storage); } // Saves local energies to the buffer. profiler_endBegin (mc_prof_wDensity); wDensity_addPoint (W_E, W_M, WTx, WTy, WTz); // H^n -> H^(n+1/2). profiler_endBegin (mc_prof_emh2); em_HStep (mcast_meshVec_RO(&E), &H); // E^n -> E^(n+1). profiler_endBegin (mc_prof_eme); em_EStep_start (&E, mcast_meshVec_RO(&H)); // Gets full picture of the currents. profiler_endBegin (mc_prof_jbcFinish); jbc_finish (&J); profiler_endBegin (mc_prof_plasma_pbcRecv); comm_plasma_complete (1000); profiler_endBegin (mc_prof_EFinish); em_EStep_finish (&E, &H, mcast_meshVec_RO(&J)); // Gauss law test ending. gauss_after (mcast_meshVec_RO(&J), mcast_meshVec_RO(&E)); // Tecplot's diagnostic check-pointing. if (chPoint_tecplot > 0 && t%chPoint_tecplot == 0) { say_doing ("writing tecplot mesh..."); profiler_endBegin (mc_prof_tecRhoJ); tecIO_saveCurrents (mcast_meshVec_RO(&J), mcast_meshDouble_RO(&rho)); } // Updates time after successful time step. parameter_setTime (Time + tau); tmp_update_gamma(countCore, countAll); // TEMP tmp_update_gamma(0, countShell); // TEMP // System check-point. if (t && t%chPoint_full == 0) { tmp_save_gamma(sysNum, cpu_here); // TEMP timeTick_t startWrite; time_get (&startWrite); say_doing ("writing check-point..."); profiler_endBegin (mc_prof_sysSave); plasma_save (sysNum, cpu_here); sysIO_save (Time, mcast_meshVec_RO(&E), mcast_meshVec_RO(&H)); profiler_endBegin (mc_prof_wDensityFlush); // WARNING: barrier-type calls inside. wDensity_flushData (); oldTime = Time; // Updates estimate of saving time. timeTick_t endWrite; time_get (&endWrite); stopFlag_saveTime = time_elapsed (&startWrite, &endWrite); } profiler_endBegin (mc_prof_catchStop); // Gets data sent earlier. if (chPoint_stopRequest > 0 && t % chPoint_stopRequest == 0) { stopFlag = main_catchStopFlag (); } profiler_end (); say_doing ("time=%.4f (%.2f %%) ", Time, 100.0*t/(double) totalSteps); // say ("step %d: time=%.4f (%.2f %%)", t, Time // , 100.0*t/(double) totalSteps); profiler_finishLoop (); } computTime = MPI_Wtime () - computTime; say ("main: main loop have taken %f sec.", computTime); // System check-point. if (oldTime != Time) { say ("Addional check-point to save the final state."); plasma_save (sysNum, cpu_here); sysIO_save (Time, mcast_meshVec_RO(&E), mcast_meshVec_RO(&H)); } say ("Final barrier."); MPI_Barrier (MPI_COMM_WORLD); // Removes tmp file to signal the end of run. if (!cpu_here) remove ("tmp/stop.flag"); return EXIT_SUCCESS; }
/** * position must be a list * If the list consists of two numbers (x y) the surface will be rendered at location x,y * the same is true for (plain x y) * (x y) * (plain x y) x,y = numbers, rendered with top left corner at x,y with scale=1 * (full) fullscreen * (centered) * (scaled) * (sized) * (rotated) * (windowed) */ Bool graphics_render_at_position(Renderable *renderable, Value position, Environment *environment) { if (environment -> fast_run) {return false;} profiler_start(profile_render); Double width = renderable -> width; Double height = renderable -> height; Double screen_width = environment -> width; Double screen_height = environment -> height; cairo_save(environment -> cairo); if (position.type == NIL) { cairo_scale(environment -> cairo, screen_width/width, screen_height/height); goto RENDER; } if (!IS_LIST(position)) { log_error_in; goto ERROR; } if (position.type != CONS) { log_error_in; goto ERROR; } Value length_val = list_length(position); if (length_val.type != INTEGER) { log_error_in; goto ERROR; } Unt length = NUM_VAL(length_val); Value first = NEXT(position); if (first.type == SYMBOL) { if (equal(first, symbols_plain)) { /**** plain ****/ /* Render at coords, unscaled */ if (length == 3) { Value x = NEXT(position); Value y = NEXT(position); if (IS_NUMERIC(x) && IS_NUMERIC(y)) { cairo_translate(environment -> cairo, NUM_VAL(x), NUM_VAL(y)); goto RENDER; } /* Return a specific error? */ } } else if (equal(first, symbols_full)) { /**** full ****/ /* Stretch image to fill entire screen */ if (length == 1) { cairo_scale(environment -> cairo, screen_width/width, screen_height/height); goto RENDER; } } else if (equal(first, symbols_centered)) { /**** centered ****/ if (length == 3) { Value x = NEXT(position); Value y = NEXT(position); if (x.type == INTEGER && y.type == INTEGER) { /* Render offset from center */ Double dx = (screen_width - width) / 2 + NUM_VAL(x); Double dy = (screen_height - height) / 2 + NUM_VAL(y); cairo_translate(environment -> cairo, dx, dy); goto RENDER; } if (x.type == FLOAT && y.type == FLOAT) { /* As in sized */ Double dx = (screen_width - width) / 2 + ((screen_width - width)/2 * NUM_VAL(x)); Double dy = (screen_height - height) / 2 + ((screen_height - height)/2 * NUM_VAL(y)); cairo_translate(environment -> cairo, dx, dy); goto RENDER; } } else if (length == 1) { Double dx = (screen_width - width) / 2; Double dy = (screen_height - height) / 2; cairo_translate(environment -> cairo, dx, dy); } } else if (equal(first, symbols_scaled)) { /**** scaled ****/ /* ('scaled x y scale) */ /* ('scaled x y scalex scaley) */ /* TODO: make it work with relative float positions */ if (length < 4 || length > 5) { log_error_in; goto ERROR; } Value x_val = NEXT(position); Value y_val = NEXT(position); Value scale_x = NEXT(position); Value scale_y = scale_x; if (length == 5) { scale_y = NEXT(position); } Double new_width; Double new_height; if (scale_x.type == INTEGER) { new_width = NUM_VAL(scale_x); } else if (scale_x.type == FLOAT) { new_width = width * NUM_VAL(scale_x); } else { log_error_in; goto ERROR; } if (scale_y.type == INTEGER) { new_height = NUM_VAL(scale_y); } else if (scale_y.type == FLOAT) { new_height = height * NUM_VAL(scale_y); } else { log_error_in; goto ERROR; } Double x = 0; Double y = 0; if (x_val.type == INTEGER) { x = NUM_VAL(x_val); } else if (x_val.type == FLOAT) { x = (screen_width - new_width) / 2 + ((screen_width - new_width)/2 * NUM_VAL(x_val)); } else { log_error_in; goto ERROR; } if (y_val.type == INTEGER) { y = NUM_VAL(y_val); } else if (y_val.type == FLOAT) { y = (screen_height - new_height) / 2 + ((screen_height - new_height)/2 * NUM_VAL(y_val)); } else { log_error_in; goto ERROR; } cairo_translate(environment -> cairo, x, y); cairo_scale(environment -> cairo, new_width/width, new_height/height); goto RENDER; } else if (equal(first, symbols_sized)) { /**** sized ****/ /* ('sized x y sizex/boundx sizey/boundy) */ /* Render scaled but keep aspect ratio */ if (length < 4 || length > 5) { log_error_in; goto ERROR; } Value x_val = NEXT(position); Value y_val = NEXT(position); Value size_x = NEXT(position); Value size_y = size_x; if (length == 5) { size_y = NEXT(position); } Double desired_width; Double desired_height; if (size_x.type == INTEGER) { desired_width = NUM_VAL(size_x); } else if (size_x.type == FLOAT) { desired_width = screen_width * NUM_VAL(size_x); } else { log_error_in; goto ERROR; } if (size_y.type == INTEGER) { desired_height = NUM_VAL(size_y); } else if (size_y.type == FLOAT) { desired_height = screen_height * NUM_VAL(size_y); } else { log_error_in; goto ERROR; } Double new_width; Double new_height; Double ratio_w = desired_width / width; Double ratio_h = desired_height / height; if (ratio_w <= ratio_h) { new_height = desired_width * ((Double) height / (Double) width); new_width = desired_width; } else { new_width = desired_height * ((Double) width / (Double) height); new_height = desired_height; } Double x = 0; Double y = 0; if (x_val.type == INTEGER) { x = NUM_VAL(x_val); } else if (x_val.type == FLOAT) { x = (screen_width - new_width) / 2 + ((screen_width - new_width)/2 * NUM_VAL(x_val)); } else { log_error_in; goto ERROR; } if (y_val.type == INTEGER) { y = NUM_VAL(y_val); } else if (y_val.type == FLOAT) { y = (screen_height - new_height) / 2 + ((screen_height - new_height)/2 * NUM_VAL(y_val)); } else { log_error_in; goto ERROR; } cairo_translate(environment -> cairo, x, y); cairo_scale(environment -> cairo, new_width/width, new_height/height); goto RENDER; } else if (equal(first, symbols_rotated)) { /**** Rotated ****/ if (length < 4) { log_error_in; goto ERROR; } Value angle_v = NEXT(position); if (!IS_NUMERIC(angle_v)) { log_error_in; goto ERROR; } Double angle = NUM_VAL(angle_v); Value x = NEXT(position); Value y = NEXT(position); if (!IS_NUMERIC(x) || !IS_NUMERIC(y)) { log_error_in; goto ERROR; } Double dx = NUM_VAL(x); Double dy = NUM_VAL(y); Value scale_x; Value scale_y; if (length == 5) { scale_x = NEXT(position); scale_y = scale_x; } else if (length == 6) { scale_x = NEXT(position); scale_y = NEXT(position); } else { log_error_in; goto ERROR; } Double sx; Double sy; if (scale_x.type == INTEGER && scale_y.type == INTEGER) { sx = NUM_VAL(scale_x)/width; sy = NUM_VAL(scale_y)/height; } else if (scale_x.type == FLOAT && scale_y.type == FLOAT) { sx = NUM_VAL(scale_x); sy = NUM_VAL(scale_y); } else { log_error_in; goto ERROR; } if (sx == 0.0 || sy == 0.0) { /* Scaled to 0, thus is not shown. Cairo freezes if given scales of 0 */ return true; } cairo_translate(environment -> cairo, dx, dy); cairo_translate(environment -> cairo, sx*width/2, sx*height/2); cairo_rotate(environment -> cairo, angle); cairo_scale(environment -> cairo, sx, sy); cairo_translate(environment -> cairo, -width/2, -height/2); goto RENDER; } } else if (IS_NUMERIC(first) && length == 2) {/* (x y) */ Value second = NEXT(position); if (IS_NUMERIC(second)) { Double x = NUM_VAL(first); Double y = NUM_VAL(second); cairo_translate(environment -> cairo, x, y); goto RENDER; } } ERROR: cairo_restore(environment -> cairo); profiler_end(profile_render); return false; RENDER: renderable -> render(renderable -> data, environment); /* cairo_set_source_surface(environment -> cairo, surface, 0, 0); */ /* cairo_paint(environment -> cairo); */ cairo_restore(environment -> cairo); profiler_end(profile_render); return true; }