Skip to content
This repository was archived by the owner on Mar 20, 2023. It is now read-only.

Commit 7799a94

Browse files
authored
Add ETA while execution of psolve (#87)
1 parent 67a05f3 commit 7799a94

File tree

3 files changed

+335
-10
lines changed

3 files changed

+335
-10
lines changed

coreneuron/nrnoc/fadvance_core.c

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ THE POSSIBILITY OF SUCH DAMAGE.
3232
#include "coreneuron/nrnoc/nrnoc_decl.h"
3333
#include "coreneuron/nrniv/nrn_acc_manager.h"
3434
#include "coreneuron/coreneuron.h"
35-
extern nrn_flush_reports(double t); // TODO remove when this file goes as cpp
35+
#include "coreneuron/utils/progressbar/progressbar.h"
36+
37+
extern void nrn_flush_reports(double t);
3638
static void* nrn_fixed_step_thread(NrnThread*);
3739
static void* nrn_fixed_step_group_thread(NrnThread*);
3840

@@ -58,7 +60,6 @@ void nrn_fixed_step_minimal() { /* not so minimal anymore with gap junctions */
5860
} else {
5961
dt2thread(dt);
6062
}
61-
/*printf("nrn_fixed_step_minimal t=%g\n", t);*/
6263
nrn_thread_table_check();
6364
nrn_multithread_job(nrn_fixed_step_thread);
6465
if (nrn_have_gaps) {
@@ -79,6 +80,26 @@ integration interval before joining
7980
static int step_group_n;
8081
static int step_group_begin;
8182
static int step_group_end;
83+
static progressbar *progress;
84+
85+
void initialize_progress_bar(int nstep) {
86+
if (nrnmpi_myid == 0) {
87+
printf("\n");
88+
progress = progressbar_new(" psolve", nstep);
89+
}
90+
}
91+
92+
void update_progress_bar(int step, double time) {
93+
if (nrnmpi_myid == 0) {
94+
progressbar_update(progress, step, time);
95+
}
96+
}
97+
98+
void finalize_progress_bar() {
99+
if (nrnmpi_myid == 0) {
100+
progressbar_finish(progress);
101+
}
102+
}
82103

83104
void nrn_fixed_step_group_minimal(int n) {
84105
static int step = 0;
@@ -87,6 +108,8 @@ void nrn_fixed_step_group_minimal(int n) {
87108
step_group_n = n;
88109
step_group_begin = 0;
89110
step_group_end = 0;
111+
initialize_progress_bar(step_group_n);
112+
90113
while (step_group_end < step_group_n) {
91114
nrn_multithread_job(nrn_fixed_step_group_thread);
92115
#if NRNMPI
@@ -99,17 +122,12 @@ void nrn_fixed_step_group_minimal(int n) {
99122
if (stoprun) {
100123
break;
101124
}
102-
step_group_begin = step_group_end;
103125
step++;
104-
105-
//@TODO: flush/optimize/better way
106-
if (nrnmpi_myid == 0) {
107-
float completed = (((float)step_group_end / step_group_n) * 100.0);
108-
printf(" Completed %.2f, t = %lf\r", completed, nrn_threads[0]._t);
109-
fflush(stdout);
110-
}
126+
step_group_begin = step_group_end;
127+
update_progress_bar(step_group_end, nrn_threads[0]._t);
111128
}
112129
t = nrn_threads[0]._t;
130+
finalize_progress_bar();
113131
}
114132

115133
static void* nrn_fixed_step_group_thread(NrnThread* nth) {
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
/**
2+
* \file
3+
* \author Trevor Fountain
4+
* \author Johannes Buchner
5+
* \author Erik Garrison
6+
* \date 2010-2014
7+
* \copyright BSD 3-Clause
8+
*
9+
* progressbar -- a C class (by convention) for displaying progress
10+
* on the command line (to stdout).
11+
*/
12+
13+
#include <assert.h>
14+
#include <limits.h>
15+
#include "progressbar.h"
16+
17+
/// How wide we assume the screen is if termcap fails.
18+
enum { DEFAULT_SCREEN_WIDTH = 80 };
19+
20+
/// The smallest that the bar can ever be (not including borders)
21+
enum { MINIMUM_BAR_WIDTH = 10 };
22+
23+
/// The format in which the estimated remaining time will be reported
24+
static const char* const ETA_FORMAT = "t: %-6.2f ETA:%2dh%02dm%02ds";
25+
26+
/// The maximum number of characters that the ETA_FORMAT can ever yield
27+
enum { ETA_FORMAT_LENGTH = 13 };
28+
29+
/// Amount of screen width taken up by whitespace (i.e. whitespace between label/bar/ETA components)
30+
enum { WHITESPACE_LENGTH = 2 };
31+
32+
/// The amount of width taken up by the border of the bar component.
33+
enum { BAR_BORDER_WIDTH = 2 };
34+
35+
/// Models a duration of time broken into hour/minute/second components. The number of seconds
36+
/// should be less than the
37+
/// number of seconds in one minute, and the number of minutes should be less than the number of
38+
/// minutes in one hour.
39+
typedef struct {
40+
int hours;
41+
int minutes;
42+
int seconds;
43+
} progressbar_time_components;
44+
45+
static void progressbar_draw(const progressbar* bar);
46+
47+
/**
48+
* Create a new progress bar with the specified label, max number of steps, and format string.
49+
* Note that `format` must be exactly three characters long, e.g. "<->" to render a progress
50+
* bar like "<---------->". Returns NULL if there isn't enough memory to allocate a progressbar
51+
*/
52+
progressbar* progressbar_new_with_format(const char* label, unsigned long max, const char* format) {
53+
progressbar* new = malloc(sizeof(progressbar));
54+
if (new == NULL) {
55+
return NULL;
56+
}
57+
58+
new->max = max;
59+
new->value = 0;
60+
new->t = 0;
61+
new->start = time(NULL);
62+
assert(3 == strlen(format) && "format must be 3 characters in length");
63+
new->format.begin = format[0];
64+
new->format.fill = format[1];
65+
new->format.end = format[2];
66+
67+
progressbar_update_label(new, label);
68+
progressbar_draw(new);
69+
70+
return new;
71+
}
72+
73+
/**
74+
* Create a new progress bar with the specified label and max number of steps.
75+
*/
76+
progressbar* progressbar_new(const char* label, unsigned long max) {
77+
return progressbar_new_with_format(label, max, "|=|");
78+
}
79+
80+
void progressbar_update_label(progressbar* bar, const char* label) {
81+
bar->label = label;
82+
}
83+
84+
/**
85+
* Delete an existing progress bar.
86+
*/
87+
void progressbar_free(progressbar* bar) {
88+
free(bar);
89+
}
90+
91+
/**
92+
* Increment an existing progressbar by `value` steps.
93+
*/
94+
void progressbar_update(progressbar* bar, unsigned long value, double t) {
95+
bar->value = value;
96+
bar->t = t;
97+
progressbar_draw(bar);
98+
}
99+
100+
/**
101+
* Increment an existing progressbar by a single step.
102+
*/
103+
void progressbar_inc(progressbar* bar, double t) {
104+
progressbar_update(bar, bar->value + 1, t);
105+
}
106+
107+
static void progressbar_write_char(FILE* file, const int ch, const size_t times) {
108+
size_t i;
109+
for (i = 0; i < times; ++i) {
110+
fputc(ch, file);
111+
}
112+
}
113+
114+
static int progressbar_max(int x, int y) {
115+
return x > y ? x : y;
116+
}
117+
118+
static unsigned int get_screen_width(void) {
119+
return DEFAULT_SCREEN_WIDTH;
120+
}
121+
122+
static int progressbar_bar_width(int screen_width, int label_length) {
123+
return progressbar_max(MINIMUM_BAR_WIDTH,
124+
screen_width - label_length - ETA_FORMAT_LENGTH - WHITESPACE_LENGTH);
125+
}
126+
127+
static int progressbar_label_width(int screen_width, int label_length, int bar_width) {
128+
int eta_width = ETA_FORMAT_LENGTH;
129+
130+
// If the progressbar is too wide to fit on the screen, we must sacrifice the label.
131+
if (label_length + 1 + bar_width + 1 + ETA_FORMAT_LENGTH > screen_width) {
132+
return progressbar_max(0, screen_width - bar_width - eta_width - WHITESPACE_LENGTH);
133+
} else {
134+
return label_length;
135+
}
136+
}
137+
138+
static int progressbar_remaining_seconds(const progressbar* bar) {
139+
double offset = difftime(time(NULL), bar->start);
140+
if (bar->value > 0 && offset > 0) {
141+
return (offset / (double)bar->value) * (bar->max - bar->value);
142+
} else {
143+
return 0;
144+
}
145+
}
146+
147+
static progressbar_time_components progressbar_calc_time_components(int seconds) {
148+
int hours = seconds / 3600;
149+
seconds -= hours * 3600;
150+
int minutes = seconds / 60;
151+
seconds -= minutes * 60;
152+
153+
progressbar_time_components components = {hours, minutes, seconds};
154+
return components;
155+
}
156+
157+
static void progressbar_draw(const progressbar* bar) {
158+
int screen_width = get_screen_width();
159+
int label_length = strlen(bar->label);
160+
int bar_width = progressbar_bar_width(screen_width, label_length);
161+
int label_width = progressbar_label_width(screen_width, label_length, bar_width);
162+
163+
int progressbar_completed = (bar->value >= bar->max);
164+
int bar_piece_count = bar_width - BAR_BORDER_WIDTH;
165+
int bar_piece_current = (progressbar_completed)
166+
? bar_piece_count
167+
: bar_piece_count * ((double)bar->value / bar->max);
168+
169+
progressbar_time_components eta =
170+
(progressbar_completed)
171+
? progressbar_calc_time_components(difftime(time(NULL), bar->start))
172+
: progressbar_calc_time_components(progressbar_remaining_seconds(bar));
173+
174+
if (label_width == 0) {
175+
// The label would usually have a trailing space, but in the case that we don't print
176+
// a label, the bar can use that space instead.
177+
bar_width += 1;
178+
} else {
179+
// Draw the label
180+
fwrite(bar->label, 1, label_width, stdout);
181+
fputc(' ', stdout);
182+
}
183+
184+
// Draw the progressbar
185+
fputc(bar->format.begin, stdout);
186+
progressbar_write_char(stdout, bar->format.fill, bar_piece_current);
187+
progressbar_write_char(stdout, ' ', bar_piece_count - bar_piece_current);
188+
fputc(bar->format.end, stdout);
189+
190+
// Draw the ETA
191+
fputc(' ', stdout);
192+
fprintf(stdout, ETA_FORMAT, bar->t, eta.hours, eta.minutes, eta.seconds);
193+
fputc('\r', stdout);
194+
}
195+
196+
/**
197+
* Finish a progressbar, indicating 100% completion, and free it.
198+
*/
199+
void progressbar_finish(progressbar* bar) {
200+
// Make sure we fill the progressbar so things look complete.
201+
progressbar_draw(bar);
202+
203+
// Print a newline, so that future outputs to stdout look prettier
204+
fprintf(stdout, "\n");
205+
206+
// We've finished with this progressbar, so go ahead and free it.
207+
progressbar_free(bar);
208+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/**
2+
* \file
3+
* \author Trevor Fountain
4+
* \author Johannes Buchner
5+
* \author Erik Garrison
6+
* \date 2010-2014
7+
* \copyright BSD 3-Clause
8+
*
9+
* progressbar -- a C class (by convention) for displaying progress
10+
* on the command line (to stderr).
11+
*/
12+
13+
#ifndef PROGRESSBAR_H
14+
#define PROGRESSBAR_H
15+
16+
#include <time.h>
17+
#include <stdio.h>
18+
#include <stdlib.h>
19+
#include <string.h>
20+
21+
#ifdef __cplusplus
22+
extern "C" {
23+
#endif
24+
25+
/**
26+
* Progressbar data structure (do not modify or create directly)
27+
*/
28+
typedef struct _progressbar_t {
29+
/// maximum value
30+
unsigned long max;
31+
32+
/// current value
33+
unsigned long value;
34+
35+
/// time progressbar was started
36+
time_t start;
37+
38+
/// label
39+
const char* label;
40+
41+
/// current time (added for simulation)
42+
double t;
43+
44+
/// characters for the beginning, filling and end of the
45+
/// progressbar. E.g. |### | has |#|
46+
struct {
47+
char begin;
48+
char fill;
49+
char end;
50+
} format;
51+
} progressbar;
52+
53+
/// Create a new progressbar with the specified label and number of steps.
54+
///
55+
/// @param label The label that will prefix the progressbar.
56+
/// @param max The number of times the progressbar must be incremented before it is considered
57+
/// complete, or, in other words, the number of tasks that this progressbar is tracking.
58+
/// @return A progressbar configured with the provided arguments. Note that the user is responsible
59+
/// for disposing of the progressbar via progressbar_finish when finished with the object.
60+
progressbar* progressbar_new(const char* label, unsigned long max);
61+
62+
/// Create a new progressbar with the specified label, number of steps, and format string.
63+
///
64+
/// @param label The label that will prefix the progressbar.
65+
/// @param max The number of times the progressbar must be incremented before it is considered
66+
/// complete, or, in other words, the number of tasks that this progressbar is tracking.
67+
/// @param format The format of the progressbar. The string provided must be three characters, and
68+
/// it will be interpretted with the first character as the left border of the bar, the second
69+
/// character of the bar and the third character as the right border of the bar. For example,
70+
/// "<->" would result in a bar formatted like "<------ >".
71+
///
72+
/// @return A progressbar configured with the provided arguments. Note that the user is responsible
73+
/// for disposing of the progressbar via progressbar_finish when finished with the object.
74+
progressbar* progressbar_new_with_format(const char* label, unsigned long max, const char* format);
75+
76+
/// Free an existing progress bar. Don't call this directly; call *progressbar_finish* instead.
77+
void progressbar_free(progressbar* bar);
78+
79+
/// Increment the given progressbar. Don't increment past the initialized # of steps, though.
80+
void progressbar_inc(progressbar* bar, double t);
81+
82+
/// Set the current status on the given progressbar.
83+
void progressbar_update(progressbar* bar, unsigned long value, double t);
84+
85+
/// Set the label of the progressbar. Note that no rendering is done. The label is simply set so
86+
/// that the next rendering will use the new label. To immediately see the new label, call
87+
/// progressbar_draw.
88+
/// Does not update display or copy the label
89+
void progressbar_update_label(progressbar* bar, const char* label);
90+
91+
/// Finalize (and free!) a progressbar. Call this when you're done, or if you break out
92+
/// partway through.
93+
void progressbar_finish(progressbar* bar);
94+
95+
#ifdef __cplusplus
96+
}
97+
#endif
98+
99+
#endif

0 commit comments

Comments
 (0)