Skip to content

Commit f2d42d9

Browse files
Copilotivan-pi
andauthored
Oregonator: switch work-precision to error vs CPU time and add gnuplot solution output (#41)
* Update Oregonator to use CPU-time work-precision and write solution file Agent-Logs-Url: https://github.com/ivan-pi/stiff3/sessions/3708a539-8772-4780-8843-43a69f3c3d4c Co-authored-by: ivan-pi <21085643+ivan-pi@users.noreply.github.com> * Finalize Oregonator CPU-time diagram and gnuplot solution output Agent-Logs-Url: https://github.com/ivan-pi/stiff3/sessions/3708a539-8772-4780-8843-43a69f3c3d4c Co-authored-by: ivan-pi <21085643+ivan-pi@users.noreply.github.com> * Harden Oregonator CPU-time and generic solution output formatting Agent-Logs-Url: https://github.com/ivan-pi/stiff3/sessions/3708a539-8772-4780-8843-43a69f3c3d4c Co-authored-by: ivan-pi <21085643+ivan-pi@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ivan-pi <21085643+ivan-pi@users.noreply.github.com>
1 parent 2f41df8 commit f2d42d9

2 files changed

Lines changed: 69 additions & 29 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fpm run --example <name>
8282

8383
With CMake, the compiled executables are placed in the `build/example/` directory and can be run directly or via CTest.
8484

85-
The `oregonator` example verifies a published reference solution at `t = 360` and writes `oregonator_work_precision.csv` together with an `oregonator_work_precision.svg` plot in the current working directory.
85+
The `oregonator` example verifies a published reference solution at `t = 360` and writes `oregonator_work_precision.csv`, an `oregonator_work_precision.svg` (error vs CPU time) plot, and `oregonator_solution.dat` (columns `t y1 y2 y3` for gnuplot) in the current working directory.
8686

8787
## Usage
8888

example/oregonator.f90

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,19 @@ program oregonator
1717
1.0e-4_wp, 1.0e-5_wp, 1.0e-6_wp, 1.0e-7_wp, 1.0e-8_wp, 1.0e-9_wp ]
1818
character(len=*), parameter :: csv_file = 'oregonator_work_precision.csv'
1919
character(len=*), parameter :: svg_file = 'oregonator_work_precision.svg'
20+
character(len=*), parameter :: solution_file = 'oregonator_solution.dat'
2021

2122
integer :: i
23+
integer :: solution_unit
2224
integer :: verification_stats(6)
2325
integer :: stats(6,ncases)
24-
real(wp) :: y(n), w(n), errors(ncases), work(ncases), verification_error
26+
real(wp) :: y(n), w(n), errors(ncases), cpu_times(ncases), verification_error, verification_cpu
27+
logical :: solution_output_enabled
2528

2629
w = 1.0_wp
30+
solution_output_enabled = .false.
2731

28-
call integrate_case(1.0e-8_wp, y, verification_stats)
32+
call integrate_case(1.0e-8_wp, y, verification_stats, verification_cpu, solution_file)
2933
verification_error = max_relative_error(y, yref)
3034
if (verification_error > verification_tol) then
3135
print '(A,ES12.4,A,ES12.4)', &
@@ -36,38 +40,74 @@ program oregonator
3640

3741
print '(A,ES12.4)', 'verified reference solution with max relative error ', verification_error
3842
print '(A,3(1X,ES24.16))', 'y(360) =', y
43+
print '(A,1X,ES12.4,1X,A)', 'verification cpu time:', verification_cpu, 's'
3944
print '(A,6(I0,1X))', 'verification stats [nacc nrej nfev njev nlu nsol]: ', verification_stats
4045

4146
do i = 1, ncases
42-
call integrate_case(eps_values(i), y, stats(:,i))
47+
call integrate_case(eps_values(i), y, stats(:,i), cpu_times(i))
4348
errors(i) = max_relative_error(y, yref)
44-
work(i) = real(stats(3,i), wp)
4549
end do
4650

47-
call write_csv(csv_file, eps_values, errors, stats)
48-
call write_svg(svg_file, eps_values, errors, work)
51+
call write_csv(csv_file, eps_values, errors, cpu_times, stats)
52+
call write_svg(svg_file, eps_values, errors, cpu_times)
4953

5054
print '(A)', 'work-precision data:'
51-
print '(A)', ' eps error nfev njev nlu nsol'
55+
print '(A)', ' eps error cpu[s] nfev njev nlu nsol'
5256
do i = 1, ncases
53-
print '(2(1X,ES10.2),4(1X,I6))', eps_values(i), errors(i), &
57+
print '(3(1X,ES10.2),4(1X,I6))', eps_values(i), errors(i), cpu_times(i), &
5458
stats(3,i), stats(4,i), stats(5,i), stats(6,i)
5559
end do
5660
print '(A,1X,A)', 'wrote', csv_file
5761
print '(A,1X,A)', 'wrote', svg_file
62+
print '(A,1X,A)', 'wrote', solution_file
5863

5964
contains
6065

61-
subroutine integrate_case(eps, y, stats)
66+
subroutine integrate_case(eps, y, stats, cpu_time_seconds, solution_filename)
6267
real(wp), intent(in) :: eps
6368
real(wp), intent(out) :: y(n)
6469
integer, intent(out) :: stats(6)
70+
real(wp), intent(out) :: cpu_time_seconds
71+
character(len=*), intent(in), optional :: solution_filename
6572

66-
real(wp) :: h0
73+
integer :: ios
74+
real(wp), parameter :: min_cpu_time = 1.0e-12_wp
75+
real(wp) :: cpu_start, cpu_end, h0
76+
logical :: write_solution
6777

6878
y = y0
6979
h0 = h0_initial
70-
call stiff3(n, fun, x0, y, x1, jac, h0, eps, w, stats=stats)
80+
write_solution = present(solution_filename)
81+
if (write_solution) then
82+
open(newunit=solution_unit, file=solution_filename, status='replace', action='write', iostat=ios)
83+
if (ios /= 0) error stop 'failed to open solution output file'
84+
write(solution_unit,'(A)') '# t y1 y2 y3'
85+
solution_output_enabled = .true.
86+
end if
87+
88+
call cpu_time(cpu_start)
89+
call stiff3(n, fun, x0, y, x1, jac, h0, eps, w, solout=output_solution, stats=stats)
90+
call cpu_time(cpu_end)
91+
cpu_time_seconds = max(min_cpu_time, cpu_end - cpu_start)
92+
93+
if (write_solution) then
94+
close(solution_unit)
95+
solution_output_enabled = .false.
96+
end if
97+
end subroutine
98+
99+
subroutine output_solution(nr, xold, x, y, iha, qa, irtrn)
100+
integer, intent(in) :: nr
101+
real(wp), intent(in) :: xold
102+
real(wp), intent(in) :: x
103+
real(wp), intent(in) :: y(:)
104+
integer, intent(in) :: iha
105+
real(wp), intent(in) :: qa
106+
integer, intent(inout) :: irtrn
107+
108+
if (solution_output_enabled) then
109+
write(solution_unit,'(ES24.16,1X,*(ES24.16,1X))') x, y
110+
end if
71111
end subroutine
72112

73113
function max_relative_error(y, y_reference) result(err)
@@ -77,28 +117,28 @@ function max_relative_error(y, y_reference) result(err)
77117
err = maxval(abs(y - y_reference)/max(1.0_wp, abs(y_reference)))
78118
end function
79119

80-
subroutine write_csv(filename, eps, err, stats)
120+
subroutine write_csv(filename, eps, err, cpu, stats)
81121
character(len=*), intent(in) :: filename
82-
real(wp), intent(in) :: eps(:), err(:)
122+
real(wp), intent(in) :: eps(:), err(:), cpu(:)
83123
integer, intent(in) :: stats(:,:)
84124

85125
integer :: i, ios, unit
86126

87127
open(newunit=unit, file=filename, status='replace', action='write', iostat=ios)
88128
if (ios /= 0) error stop 'failed to open CSV output file'
89129

90-
write(unit,'(A)') 'eps,max_relative_error,nfev,njev,nlu,nsol,nacc,nrej'
130+
write(unit,'(A)') 'eps,max_relative_error,cpu_time_seconds,nfev,njev,nlu,nsol,nacc,nrej'
91131
do i = 1, size(eps)
92-
write(unit,'(ES24.16,'','',ES24.16,'','',I0,'','',I0,'','',I0,'','',I0,'','',I0,'','',I0)') &
93-
eps(i), err(i), stats(3,i), stats(4,i), stats(5,i), stats(6,i), stats(1,i), stats(2,i)
132+
write(unit,'(ES24.16,'','',ES24.16,'','',ES24.16,'','',I0,'','',I0,'','',I0,'','',I0,'','',I0,'','',I0)') &
133+
eps(i), err(i), cpu(i), stats(3,i), stats(4,i), stats(5,i), stats(6,i), stats(1,i), stats(2,i)
94134
end do
95135

96136
close(unit)
97137
end subroutine
98138

99-
subroutine write_svg(filename, eps, err, work)
139+
subroutine write_svg(filename, eps, err, cpu)
100140
character(len=*), intent(in) :: filename
101-
real(wp), intent(in) :: eps(:), err(:), work(:)
141+
real(wp), intent(in) :: eps(:), err(:), cpu(:)
102142

103143
integer, parameter :: width = 800
104144
integer, parameter :: height = 600
@@ -109,15 +149,15 @@ subroutine write_svg(filename, eps, err, work)
109149

110150
character(len=32) :: label
111151
integer :: i, ios, unit
112-
real(wp) :: log_work(size(work)), log_err(size(err))
152+
real(wp) :: log_cpu(size(cpu)), log_err(size(err))
113153
real(wp) :: xmin, xmax, ymin, ymax, xpad, ypad
114154
real(wp) :: x1p, x2p, y1p, y2p, xtick, ytick, tick_value
115155

116-
log_work = log10(max(work, tiny(1.0_wp)))
156+
log_cpu = log10(max(cpu, tiny(1.0_wp)))
117157
log_err = log10(max(err, tiny(1.0_wp)))
118158

119-
xmin = minval(log_work)
120-
xmax = maxval(log_work)
159+
xmin = minval(log_cpu)
160+
xmax = maxval(log_cpu)
121161
ymin = minval(log_err)
122162
ymax = maxval(log_err)
123163
xpad = 0.05_wp*max(xmax - xmin, 1.0_wp)
@@ -163,23 +203,23 @@ subroutine write_svg(filename, eps, err, work)
163203

164204
write(unit,'(A)') &
165205
'<text x="435" y="585" font-family="sans-serif" font-size="16" ' // &
166-
'text-anchor="middle">rhs evaluations (nfev)</text>'
206+
'text-anchor="middle">CPU time [s]</text>'
167207
write(unit,'(A)') &
168208
'<text x="24" y="285" font-family="sans-serif" font-size="16" ' // &
169209
'text-anchor="middle" transform="rotate(-90 24 285)">' // &
170210
'max relative error</text>'
171211

172-
do i = 1, size(work) - 1
173-
x1p = xcoord(log_work(i), xmin, xmax, width, left, right)
212+
do i = 1, size(cpu) - 1
213+
x1p = xcoord(log_cpu(i), xmin, xmax, width, left, right)
174214
y1p = ycoord(log_err(i), ymin, ymax, height, top, bottom)
175-
x2p = xcoord(log_work(i + 1), xmin, xmax, width, left, right)
215+
x2p = xcoord(log_cpu(i + 1), xmin, xmax, width, left, right)
176216
y2p = ycoord(log_err(i + 1), ymin, ymax, height, top, bottom)
177217
write(unit,'(A,F0.3,A,F0.3,A,F0.3,A,F0.3,A)') '<line x1="', x1p, '" y1="', y1p, &
178218
'" x2="', x2p, '" y2="', y2p, '" stroke="#1f77b4" stroke-width="2"/>'
179219
end do
180220

181-
do i = 1, size(work)
182-
x1p = xcoord(log_work(i), xmin, xmax, width, left, right)
221+
do i = 1, size(cpu)
222+
x1p = xcoord(log_cpu(i), xmin, xmax, width, left, right)
183223
y1p = ycoord(log_err(i), ymin, ymax, height, top, bottom)
184224
write(label,'(ES9.1)') eps(i)
185225
write(unit,'(A,F0.3,A,F0.3,A)') '<circle cx="', x1p, '" cy="', y1p, '" r="4.5" fill="#d62728"/>'

0 commit comments

Comments
 (0)