Euler method: Difference between revisions

Line 275:
80.000 20.005
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}}==
1,448

edits