Euler method: Difference between revisions
Content added Content deleted
Line 275: | Line 275: | ||
80.000 20.005 |
80.000 20.005 |
||
90.000 20.002</pre> |
90.000 20.002</pre> |
||
=={{header|ATS}}== |
|||
{{trans|Ol}} |
|||
The following program's output should be fed to [[Gnuplot]], which will produce a PNG (using either the font that is specified by the ATS program or a fallback substitute). You can run the program with a command such as this: <code>patscc -g -O2 -std=gnu2x -DATS_MEMALLOC_LIBC euler_method_task.dats && ./a.out | gnuplot</code> |
|||
All data requiring allocation is allocated as linear types, and so is not leaked. That is, roughly speaking: it requires no garbage collection. |
|||
<syntaxhighlight lang="ats"> |
|||
#include "share/atspre_staload.hats" |
|||
staload UN = "prelude/SATS/unsafe.sats" |
|||
#define NIL list_vt_nil () |
|||
#define :: list_vt_cons |
|||
(* Approximate y(t) in dy/dt=f(t,y), y(a)=y0, t going from a to b with |
|||
positive step size h. This implementation of euler_method requires |
|||
f to be a unboxed linear closure. *) |
|||
extern fn {tk : tkind} |
|||
euler_method (f : &(g0float tk, g0float tk) -<clo1> g0float tk, |
|||
y0 : g0float tk, |
|||
a : g0float tk, |
|||
b : g0float tk, |
|||
h : g0float tk) : List1_vt @(g0float tk, g0float tk) |
|||
implement {tk} |
|||
euler_method (f, y0, a, b, h) = |
|||
let |
|||
typedef point_pair = @(g0float tk, g0float tk) |
|||
fun |
|||
loop (f : &(g0float tk, g0float tk) -<clo1> g0float tk, |
|||
t : g0float tk, |
|||
y : g0float tk, |
|||
point_pairs : List0_vt point_pair) |
|||
: List1_vt point_pair = |
|||
let |
|||
val point_pairs = @(t, y) :: point_pairs |
|||
in |
|||
if b <= t then |
|||
reverse<point_pair> point_pairs |
|||
else |
|||
loop (f, t + h, y + (h * f (t, y)), point_pairs) |
|||
end |
|||
in |
|||
loop (f, a, y0, NIL) |
|||
end |
|||
fun {tk : tkind} |
|||
write_point_pairs |
|||
(outf : FILEref, |
|||
point_pairs : !List0_vt @(g0float tk, g0float tk)) |
|||
: void = |
|||
case+ point_pairs of |
|||
| NIL => () |
|||
| (@(t, y) :: tl) => |
|||
begin |
|||
fprint_val<g0float tk> (outf, t); |
|||
fprint! (outf, " "); |
|||
fprint_val<g0float tk> (outf, y); |
|||
fprintln! (outf); |
|||
write_point_pairs (outf, tl) |
|||
end |
|||
implement |
|||
main0 () = |
|||
let |
|||
(* Implement f as a stack-allocated linear closure. *) |
|||
var f = |
|||
lam@ (t : double, y : double) : double => ~0.07 * (y - 20.0) |
|||
val data2 = euler_method<dblknd> (f, 100.0, 0.0, 100.0, 2.0) |
|||
and data5 = euler_method<dblknd> (f, 100.0, 0.0, 100.0, 5.0) |
|||
and data10 = euler_method<dblknd> (f, 100.0, 0.0, 100.0, 10.0) |
|||
val outf = stdout_ref |
|||
in |
|||
fprintln! (outf, "set encoding utf8"); |
|||
fprintln! (outf, "set term png size 1000,750 font 'RTF Amethyst Pro,16'"); |
|||
fprintln! (outf, "set output 'newton-cooling-ATS.png'"); |
|||
fprintln! (outf, "set grid"); |
|||
fprintln! (outf, "set title 'Newton’s Law of Cooling'"); |
|||
fprintln! (outf, "set xlabel 'Elapsed time (seconds)'"); |
|||
fprintln! (outf, "set ylabel 'Temperature (Celsius)'"); |
|||
fprintln! (outf, "set xrange [0:100]"); |
|||
fprintln! (outf, "set yrange [15:100]"); |
|||
fprintln! (outf, "y(x) = 20.0 + (80.0 * exp (-0.07 * x))"); |
|||
fprintln! (outf, "plot y(x) with lines title 'Analytic solution', \\"); |
|||
fprintln! (outf, " '-' with linespoints title 'Euler method, step size 2s', \\"); |
|||
fprintln! (outf, " '-' with linespoints title 'Step size 5s', \\"); |
|||
fprintln! (outf, " '-' with linespoints title 'Step size 10s'"); |
|||
write_point_pairs (outf, data2); |
|||
fprintln! (outf, "e"); |
|||
write_point_pairs (outf, data5); |
|||
fprintln! (outf, "e"); |
|||
write_point_pairs (outf, data10); |
|||
fprintln! (outf, "e"); |
|||
free data2; |
|||
free data5; |
|||
free data10 |
|||
end |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
[[File:Euler method ATS--newton-cooling.2023.04.26.12.24.43.png|thumb|none|alt=The output of the ATS program, plotted by Gnuplot.]] |
|||
=={{header|BASIC}}== |
=={{header|BASIC}}== |