This commit is contained in:
Ingy döt Net 2013-10-27 22:24:23 +00:00
parent 6f050a029e
commit 776bba907c
3887 changed files with 59894 additions and 7280 deletions

View file

@ -0,0 +1,45 @@
DELEGATE-ID func.
PROCEDURE DIVISION USING VALUE t AS FLOAT-LONG
RETURNING ret AS FLOAT-LONG.
END DELEGATE.
CLASS-ID. MainClass.
78 T0 VALUE 100.0.
78 TR VALUE 20.0.
78 k VALUE 0.07.
01 delta-t INITIALIZE ONLY STATIC
FLOAT-LONG OCCURS 3 VALUES 2.0, 5.0, 10.0.
78 n VALUE 100.
METHOD-ID NewtonCooling STATIC.
PROCEDURE DIVISION USING VALUE t AS FLOAT-LONG
RETURNING ret AS FLOAT-LONG.
COMPUTE ret = - k * (t - TR)
END METHOD.
METHOD-ID Main STATIC.
DECLARE f AS TYPE func
SET f TO METHOD self::NewtonCooling
DECLARE delta-t-len AS BINARY-LONG
MOVE delta-t::Length TO delta-t-len
PERFORM VARYING i AS BINARY-LONG FROM 1 BY 1
UNTIL i > delta-t-len
DECLARE elt AS FLOAT-LONG = delta-t (i)
INVOKE TYPE Console::WriteLine("delta-t = {0:F4}", elt)
INVOKE self::Euler(f, T0, n, elt)
END-PERFORM
END METHOD.
METHOD-ID Euler STATIC.
PROCEDURE DIVISION USING VALUE f AS TYPE func, y AS FLOAT-LONG,
n AS BINARY-LONG, h AS FLOAT-LONG.
PERFORM VARYING x AS BINARY-LONG FROM 0 BY h UNTIL x >= n
INVOKE TYPE Console::WriteLine("x = {0:F4}, y = {1:F4}", x, y)
COMPUTE y = y + h * RUN f(y)
END-PERFORM
END METHOD.
END CLASS.

View file

@ -0,0 +1,38 @@
euler_method(f, y0, a, b, h):= block(
[t: a, y: y0, tg: [a], yg: [y0]],
unless t>=b do (
t: t + h,
y: y + f(t, y)*h,
tg: endcons(t, tg),
yg: endcons(y, yg)
),
[tg, yg]
);
/* initial temperature */
T0: 100;
/* environment of temperature */
Tr: 20;
/* the cooling constant */
k: 0.07;
/* end of integration */
tmax: 100;
/* analytical solution */
Tref(t):= Tr + (T0 - Tr)*exp(-k*t);
/* cooling rate */
dT(t, T):= -k*(T-Tr);
/* get numerical solution */
h: 10;
[tg, yg]: euler_method('dT, T0, 0, tmax, h);
/* plot analytical and numerical solution */
plot2d([Tref, [discrete, tg, yg]], ['t, 0, tmax],
[legend, "analytical", concat("h = ", h)],
[xlabel, "t / seconds"],
[ylabel, "Temperature / C"]);

View file

@ -0,0 +1,10 @@
(* Euler integration by recurrence relation.
* Given a function, and stepsize, provides a function of (t,y) which
* returns the next step: (t',y'). *)
let euler f ~step (t,y) = ( t+.step, y +. step *. f t y )
(* newton_cooling doesn't use time parameter, so _ is a placeholder *)
let newton_cooling ~k ~tr _ y = -.k *. (y -. tr)
(* analytic solution for Newton cooling *)
let analytic_solution ~k ~tr ~t0 t = tr +. (t0 -. tr) *. exp (-.k *. t)

View file

@ -0,0 +1,24 @@
(* Wrapping up the parameters in a "cool" function: *)
let cool = euler (newton_cooling ~k:0.07 ~tr:20.)
(* Similarly for the analytic solution: *)
let analytic = analytic_solution ~k:0.07 ~tr:20. ~t0:100.
(* (Just a loop) Apply recurrence function on state, until some condition *)
let recur ~until f state =
let rec loop s =
if until s then ()
else loop (f s)
in loop state
(* 'results' generates the specified output starting from initial values t=0, temp=100C; ending at t=100s *)
let results fn =
Printf.printf "\t time\t euler\tanalytic\n%!";
let until (t,y) =
Printf.printf "\t%7.3f\t%7.3f\t%9.5f\n%!" t y (analytic t);
t >= 100.
in recur ~until fn (0.,100.)
results (cool ~step:10.)
results (cool ~step:5.)
results (cool ~step:2.)

View file

@ -0,0 +1,49 @@
{$mode delphi}
PROGRAM Euler;
TYPE TNewtonCooling = FUNCTION (t: REAL) : REAL;
CONST T0 : REAL = 100.0;
CONST TR : REAL = 20.0;
CONST k : REAL = 0.07;
CONST time : INTEGER = 100;
CONST step : INTEGER = 10;
CONST dt : ARRAY[0..3] of REAL = (1.0,2.0,5.0,10.0);
VAR i : INTEGER;
FUNCTION NewtonCooling(t: REAL) : REAL;
BEGIN
NewtonCooling := -k * (t-TR);
END;
PROCEDURE Euler(F: TNewtonCooling; y, h : REAL; n: INTEGER);
VAR i: INTEGER = 0;
BEGIN
WRITE('dt=',trunc(h):2,':');
REPEAT
IF (i mod 10 = 0) THEN WRITE(' ',y:2:3);
INC(i,trunc(h));
y := y + h * F(y);
UNTIL (i >= n);
WRITELN;
END;
PROCEDURE Sigma;
VAR t: INTEGER = 0;
BEGIN
WRITE('Sigma:');
REPEAT
WRITE(' ',(20 + 80 * exp(-0.07 * t)):2:3);
INC(t,step);
UNTIL (t>=time);
WRITELN;
END;
BEGIN
WRITELN('Newton cooling function: Analytic solution (Sigma) with 3 Euler approximations.');
WRITELN('Time: ',0:7,10:7,20:7,30:7,40:7,50:7,60:7,70:7,80:7,90:7);
Sigma;
FOR i := 1 to 3 DO
Euler(NewtonCooling,T0,dt[i],time);
END.

View file

@ -1,10 +1,12 @@
def euler(y0,a,b,h, &block)
t,y = a,y0
while t < b
puts "%6.3f %6.3f" % [t,y]
t += h
y += h * block.call(t,y)
def euler(y, a, b, h)
a.step(b,h) do |t|
puts "%7.3f %7.3f" % [t,y]
y += h * yield(t,y)
end
end
euler(100,0,100,10) {|time, temp| -0.07 * (temp - 20) }
[10, 5, 2].each do |step|
puts "Step = #{step}"
euler(100,0,100,step) {|time, temp| -0.07 * (temp - 20) }
puts
end