Annotation of OpenXM_contrib/PHC/Ada/Continuation/predictors.adb, Revision 1.1.1.1
1.1 maekawa 1: with Standard_Mathematical_Functions; use Standard_Mathematical_Functions;
2: with Standard_Natural_Vectors;
3: with Standard_Complex_Linear_Solvers; use Standard_Complex_Linear_Solvers;
4:
5: package body Predictors is
6:
7: -- PREDICTORS for t :
8:
9: procedure Real_Predictor
10: ( t : in out Complex_Number; target : in Complex_Number;
11: h,tol : in double_float; pow : in positive := 1;
12: hh : out double_float ) is
13:
14: nt : Complex_Number;
15:
16: begin
17: if pow = 1
18: then nt := t + Create(h);
19: else nt := Create((h+REAL_PART(t)**pow)**(1.0/double_float(pow)));
20: end if;
21: if REAL_PART(nt) >= REAL_PART(target)
22: or else abs( REAL_PART(nt) - REAL_PART(target) ) <= tol
23: then hh := REAL_PART(target) - REAL_PART(t);
24: t := target;
25: else hh := h;
26: t := nt;
27: end if;
28: end Real_Predictor;
29:
30: procedure Complex_Predictor
31: ( t : in out Complex_Number; target : in Complex_Number;
32: h,tol : in double_float; hh : out double_float;
33: distance : in double_float; trial : in natural ) is
34:
35: nt,target_direction,step : Complex_Number;
36: dre,dim,d,x,y,alfa,absnt : double_float;
37: tr3 : natural range 0..2;
38:
39: begin
40: target_direction := target - t;
41: d := AbsVal(target_direction);
42: if d < tol
43: then nt := target - Create(distance);
44: hh := AbsVal(nt - t);
45: else tr3 := trial mod 3;
46: case tr3 is
47: when 0 => target_direction := target_direction / Create(d);
48: if (d - h) > distance
49: then step := Create(h) * target_direction;
50: else step := (d - distance) * target_direction;
51: end if;
52: nt := t + step;
53: when 1 => dre := REAL_PART(target_direction);
54: dim := IMAG_PART(target_direction);
55: alfa := ARCTAN(dim/dre);
56: x := h * COS(alfa + PI/4.0);
57: y := h * SIN(alfa + PI/4.0);
58: step := Create(x,y);
59: nt := t + step;
60: absnt := AbsVal(nt);
61: if (absnt > AbsVal(target))
62: or else (AbsVal(nt - target) < distance)
63: then step := Create(0.0,y) * Create(h);
64: nt := t + step;
65: end if;
66: when 2 => dre := REAL_PART(target_direction);
67: dim := IMAG_PART(target_direction);
68: alfa := ARCTAN(dim/dre);
69: x := h * COS(alfa - PI/4.0);
70: y := h * SIN(alfa - PI/4.0);
71: step := Create(x,y);
72: nt := t + step;
73: absnt := AbsVal(nt);
74: if (absnt > AbsVal(target))
75: or else (AbsVal(nt - target) < distance)
76: then step := Create(0.0,-y) * Create(h);
77: nt := t + step;
78: end if;
79: end case;
80: hh := AbsVal(step);
81: end if;
82: t := nt;
83: end Complex_Predictor;
84:
85: procedure Circular_Predictor
86: ( t : in out Complex_Number; theta : in out double_float;
87: t0_min_target,target : in Complex_Number;
88: h : in double_float ) is
89:
90: e_i_theta : Complex_Number;
91:
92: begin
93: theta := theta + h;
94: e_i_theta := Create(COS(theta),SIN(theta));
95: t := target + t0_min_target * e_i_theta;
96: end Circular_Predictor;
97:
98: procedure Geometric_Predictor
99: ( t : in out Complex_Number; target : in Complex_Number;
100: h,tol : in double_float ) is
101:
102: nt : Complex_Number;
103:
104: begin
105: nt := target - Create(h)*(target - t);
106: if abs( REAL_PART(nt) - REAL_PART(target) ) <= tol
107: then t := target;
108: else t := nt;
109: end if;
110: end Geometric_Predictor;
111:
112: -- PREDICTORS FOR x :
113:
114: procedure Secant_Predictor
115: ( x : in out Solution_Array; prev_x : in Solution_Array;
116: fac : in Complex_Number; dist_x : in double_float ) is
117:
118: j : natural;
119: xx : Solution_Array(x'range);
120:
121: begin
122: Copy(x,xx);
123: for i in x'range loop
124: x(i).v := x(i).v + fac * ( x(i).v - prev_x(i).v );
125: j := xx'first;
126: Equals(xx,x(i).v,i,dist_x,j);
127: if j /= i
128: then Copy(xx,x);
129: exit;
130: end if;
131: end loop;
132: Clear(xx);
133: end Secant_Predictor;
134:
135: -- PREDICTORS FOR t AND x :
136:
137: procedure Secant_Single_Real_Predictor
138: ( x : in out Vector; prev_x : in Vector;
139: t : in out Complex_Number; prev_t,target : in Complex_Number;
140: h,tol : in double_float; pow : in positive := 1 ) is
141:
142: hh,tmp : double_float;
143: factor : Complex_Number;
144:
145: begin
146: tmp := AbsVal(t - prev_t);
147: Real_Predictor(t,target,h,tol,pow,hh);
148: if tmp > tol
149: then factor := Create(hh/tmp);
150: x := x + factor * ( x - prev_x );
151: end if;
152: end Secant_Single_Real_Predictor;
153:
154: procedure Secant_Multiple_Real_Predictor
155: ( x : in out Solution_Array; prev_x : in Solution_Array;
156: t : in out Complex_Number; prev_t,target : in Complex_Number;
157: h,tol,dist_x : in double_float; pow : in positive := 1 ) is
158:
159: hh,tmp : double_float;
160: factor : Complex_Number;
161:
162: begin
163: tmp := AbsVal(t - prev_t);
164: Real_Predictor(t,target,h,tol,pow,hh);
165: if tmp > tol
166: then factor := Create(hh/tmp);
167: Secant_Predictor(x,prev_x,factor,dist_x);
168: end if;
169: for k in x'range loop
170: x(k).t := t;
171: end loop;
172: end Secant_Multiple_Real_Predictor;
173:
174: procedure Secant_Single_Complex_Predictor
175: ( x : in out Vector; prev_x : in Vector;
176: t : in out Complex_Number; prev_t,target : in Complex_Number;
177: h,tol,dist_t : in double_float; trial : in natural ) is
178:
179: hh,tmp : double_float;
180: factor : Complex_Number;
181:
182: begin
183: tmp := AbsVal(t - prev_t);
184: Complex_Predictor(t,target,h,tol,hh,dist_t,trial);
185: if tmp > tol
186: then factor := Create(hh/tmp);
187: x := x + factor * ( x - prev_x );
188: end if;
189: end Secant_Single_Complex_Predictor;
190:
191: procedure Secant_Multiple_Complex_Predictor
192: ( x : in out Solution_Array; prev_x : in Solution_Array;
193: t : in out Complex_Number; prev_t,target : in Complex_Number;
194: h,tol,dist_x,dist_t : in double_float; trial : in natural ) is
195:
196: hh,tmp : double_float;
197: factor : Complex_Number;
198:
199: begin
200: tmp := AbsVal(t - prev_t);
201: Complex_Predictor(t,target,h,tol,hh,dist_t,trial);
202: if tmp > tol
203: then factor := Create(hh/tmp);
204: Secant_Predictor(x,prev_x,factor,dist_x);
205: end if;
206: for k in x'range loop
207: x(k).t := t;
208: end loop;
209: end Secant_Multiple_Complex_Predictor;
210:
211: procedure Secant_Circular_Predictor
212: ( x : in out Vector; prev_x : in Vector;
213: t : in out Complex_Number; theta : in out double_float;
214: prev_t,t0_min_target,target : in Complex_Number;
215: h,tol : in double_float ) is
216:
217: factor : Complex_Number;
218: tmp : double_float := AbsVal(t-prev_t);
219:
220: begin
221: if tmp <= tol
222: then Circular_Predictor(t,theta,t0_min_target,target,h);
223: else factor := Create(h/tmp);
224: Circular_Predictor(t,theta,t0_min_target,target,h);
225: x := x + factor * ( x - prev_x );
226: end if;
227: end Secant_Circular_Predictor;
228:
229: procedure Secant_Geometric_Predictor
230: ( x : in out Vector; prev_x : in Vector;
231: t : in out Complex_Number; prev_t,target : in Complex_Number;
232: h,tol : in double_float ) is
233:
234: dist_prev,dist : double_float;
235: factor,tmp : Complex_Number;
236:
237: begin
238: dist_prev := AbsVal(t - prev_t); -- old stepsize
239: tmp := t;
240: Geometric_Predictor(t,target,h,tol);
241: dist := AbsVal(t - tmp); -- new stepsize
242: if dist_prev > tol
243: then factor := Create(dist/dist_prev);
244: x := x + factor * ( x - prev_x );
245: end if;
246: end Secant_Geometric_Predictor;
247:
248: procedure Tangent_Single_Real_Predictor
249: ( x : in out Vector; t : in out Complex_Number;
250: target : in Complex_Number; h,tol : in double_float;
251: pow : in positive := 1 ) is
252:
253: n : natural := x'last;
254: info : integer;
255: norm_tan,hh : double_float;
256: rhs : Vector(x'range);
257: j : Matrix(1..n,1..n);
258: ipvt : Standard_Natural_Vectors.Vector(1..n);
259: prev_t : Complex_Number := t;
260:
261: begin
262: Real_Predictor(t,target,h,tol,pow,hh);
263: j := dH(x,prev_t);
264: lufac(j,n,ipvt,info);
265: if info = 0
266: then rhs := dH(x,prev_t);
267: Min(rhs);
268: lusolve(j,n,ipvt,rhs);
269: norm_tan := Norm(rhs);
270: if norm_tan > tol
271: then hh := hh / norm_tan;
272: Mul(rhs,Create(hh));
273: Add(x,rhs);
274: end if;
275: end if;
276: end Tangent_Single_Real_Predictor;
277:
278: procedure Tangent_Multiple_Real_Predictor
279: ( x : in out Solution_Array; t : in out Complex_Number;
280: target : in Complex_Number; h,tol,dist_x : in double_float;
281: nsys : in out natural; pow : in positive := 1 ) is
282:
283: n : natural := x(x'first).n;
284: norm_tan,hh : double_float;
285: rhs : Vector(1..n);
286: info : integer;
287: j : Matrix(1..n,1..n);
288: ipvt : Standard_Natural_Vectors.Vector(1..n);
289: xx : Solution_Array(x'range);
290: jj : natural;
291: prev_t : Complex_Number := t;
292:
293: begin
294: Real_Predictor(t,target,h,tol,pow,hh);
295: Copy(x,xx);
296: for i in x'range loop
297: j := dH(x(i).v,prev_t);
298: lufac(j,n,ipvt,info);
299: if info = 0
300: then rhs := dH(x(i).v,prev_t);
301: Min(rhs);
302: lusolve(j,n,ipvt,rhs);
303: nsys := nsys + 1;
304: norm_tan := Norm(rhs);
305: if norm_tan > tol
306: then hh := hh / norm_tan;
307: Mul(rhs,Create(hh));
308: Add(x(i).v,rhs);
309: end if;
310: jj := xx'first;
311: Equals(xx,x(i).v,i,dist_x,jj);
312: if jj /= i
313: then Copy(xx,x); exit;
314: end if;
315: else Copy(xx,x); exit;
316: end if;
317: end loop;
318: Clear(xx);
319: for k in x'range loop
320: x(k).t := t;
321: end loop;
322: end Tangent_Multiple_Real_Predictor;
323:
324: procedure Tangent_Single_Complex_Predictor
325: ( x : in out Vector; t : in out Complex_Number;
326: target : in Complex_Number;
327: h,tol,dist_t : in double_float; trial : in natural) is
328:
329: n : natural := x'last;
330: info : integer;
331: norm_tan,hh : double_float;
332: rhs : Vector(x'range);
333: j : Matrix(1..n,1..n);
334: ipvt : Standard_Natural_Vectors.Vector(1..n);
335: prev_t : Complex_Number := t;
336:
337: begin
338: Complex_Predictor(t,target,h,tol,hh,dist_t,trial);
339: j := dH(x,prev_t);
340: lufac(j,n,ipvt,info);
341: if info = 0
342: then rhs := dH(x,prev_t);
343: Min(rhs);
344: lusolve(j,n,ipvt,rhs);
345: norm_tan := Norm(rhs);
346: if norm_tan > tol
347: then hh := hh / norm_tan;
348: Mul(rhs,Create(hh));
349: Add(x,rhs);
350: end if;
351: end if;
352: end Tangent_Single_Complex_Predictor;
353:
354: procedure Tangent_Multiple_Complex_Predictor
355: ( x : in out Solution_Array; t : in out Complex_Number;
356: target : in Complex_Number;
357: h,tol,dist_x,dist_t : in double_float;
358: trial : in natural; nsys : in out natural) is
359:
360: n : natural := x(x'first).n;
361: norm_tan,hh : double_float;
362: rhs : Vector(1..n);
363: info : integer;
364: j : Matrix(1..n,1..n);
365: ipvt : Standard_Natural_Vectors.Vector(1..n);
366: xx : Solution_Array(x'range);
367: jj : natural;
368: prev_t : Complex_Number := t;
369:
370: begin
371: Complex_Predictor(t,target,h,tol,hh,dist_t,trial);
372: Copy(x,xx);
373: for i in x'range loop
374: j := dH(x(i).v,prev_t);
375: lufac(j,n,ipvt,info);
376: if info = 0
377: then rhs := dH(x(i).v,prev_t);
378: Min(rhs);
379: lusolve(j,n,ipvt,rhs);
380: nsys := nsys + 1;
381: norm_tan := Norm(rhs);
382: if norm_tan > tol
383: then hh := hh / norm_tan;
384: Mul(rhs,Create(hh));
385: Add(x(i).v,rhs);
386: end if;
387: jj := xx'first;
388: Equals(xx,x(i).v,i,dist_x,jj);
389: if jj /= i
390: then Copy(xx,x); exit;
391: end if;
392: else Copy(xx,x); exit;
393: end if;
394: end loop;
395: Clear(xx);
396: for k in x'range loop
397: x(k).t := t;
398: end loop;
399: end Tangent_Multiple_Complex_Predictor;
400:
401: procedure Tangent_Circular_Predictor
402: ( x : in out Vector; t : in out Complex_Number;
403: theta : in out double_float;
404: t0_min_target,target : in Complex_Number;
405: h,tol : in double_float ) is
406:
407: n : natural := x'last;
408: info : integer;
409: norm_tan : double_float;
410: rhs : Vector(x'range);
411: j : Matrix(1..n,1..n);
412: ipvt : Standard_Natural_Vectors.Vector(1..n);
413:
414: begin
415: lufac(j,n,ipvt,info);
416: if info = 0
417: then rhs := dH(x,t);
418: Min(rhs);
419: lusolve(j,n,ipvt,rhs);
420: end if;
421: Circular_Predictor(t,theta,t0_min_target,target,h);
422: if info = 0
423: then norm_tan := Norm(rhs);
424: if norm_tan > tol
425: then Mul(rhs,Create(h/norm_tan));
426: Add(x,rhs);
427: end if;
428: end if;
429: end Tangent_Circular_Predictor;
430:
431: procedure Tangent_Geometric_Predictor
432: ( x : in out Vector; t : in out Complex_Number;
433: target : in Complex_Number; h,tol : in double_float ) is
434:
435: n : natural := x'last;
436: info : integer;
437: norm_tan,step : double_float;
438: rhs : Vector(x'range);
439: j : Matrix(1..n,1..n);
440: ipvt : Standard_Natural_Vectors.Vector(1..n);
441: prev_t : Complex_Number := t;
442:
443: begin
444: Geometric_Predictor(t,target,h,tol);
445: j := dH(x,prev_t);
446: lufac(j,n,ipvt,info);
447: if info = 0
448: then rhs := dH(x,prev_t);
449: Min(rhs);
450: lusolve(j,n,ipvt,rhs);
451: norm_tan := Norm(rhs);
452: if norm_tan > tol
453: then step := AbsVal(t-prev_t) / norm_tan;
454: Mul(rhs,Create(step));
455: Add(x,rhs);
456: end if;
457: end if;
458: end Tangent_Geometric_Predictor;
459:
460: function Hermite ( t0,t1,t,x0,x1,v0,v1 : Complex_Number )
461: return Complex_Number is
462:
463: -- DESCRIPTION :
464: -- Returns the value of the third degree interpolating polynomial x(t),
465: -- such that x(t0) = x0, x(t1) = x1, x'(t0) = v0 and x'(t1) = v1.
466:
467: -- REQUIRED : t0 /= t1.
468:
469: -- IMPLEMENTATION :
470: -- x(t) = a3*t^3 + a2*t^2 + a1*t + a0,
471: -- The four interpolation conditions lead to a linear system in
472: -- the coefficients of x(t). This system is first solved explicitly
473: -- and then the polynomial x(t) is evaluated.
474:
475: a0,a1,a2,a3,t10,v10 : Complex_Number;
476:
477: begin
478: t10 := t1 - t0;
479: v10 := (x1 - x0)/t10;
480: a3 := (v1 + v0 - Create(2.0)*v10)/(t10**2);
481: a2 := (v10 - v0 - (t1**2 + t1*t0 - Create(2.0)*t0**2)*a3)/t10;
482: a1 := v0 - (Create(3.0)*a3*t0 + Create(2.0)*a2)*t0;
483: a0 := x0 - ((a3*t0 + a2)*t0 + a1)*t0;
484: return (((a3*t + a2)*t + a1)*t + a0);
485: end Hermite;
486:
487: function Hermite ( t0,t1,t : Complex_Number; x0,x1,v0,v1 : Vector )
488: return Vector is
489:
490: -- DESCRIPTION :
491: -- Returns the value of the third degree interpolating polynomial x(t),
492: -- such that x(t0) = x0, x(t1) = x1, x'(t0) = v0 and x'(t1) = v1,
493: -- for every component.
494:
495: -- REQUIRED : t0 /= t1.
496:
497: res : Vector(x0'range);
498:
499: begin
500: for i in res'range loop
501: res(i) := Hermite(t0,t1,t,x0(i),x1(i),v0(i),v1(i));
502: end loop;
503: return res;
504: end Hermite;
505:
506: procedure Hermite_Single_Real_Predictor
507: ( x : in out Vector; prev_x : in Vector;
508: t : in out Complex_Number; prev_t,target : in Complex_Number;
509: v : in out Vector; prev_v : in Vector;
510: h,tol : in double_float; pow : in positive := 1 ) is
511:
512: n : natural := x'last;
513: info : integer;
514: hh : double_float;
515: j : Matrix(1..n,1..n);
516: ipvt : Standard_Natural_Vectors.Vector(1..n);
517: t1 : Complex_Number := t;
518:
519: begin
520: Real_Predictor(t,target,h,tol,pow,hh);
521: j := dH(x,t1);
522: lufac(j,n,ipvt,info);
523: if info = 0
524: then v := dH(x,t1);
525: Min(v);
526: lusolve(j,n,ipvt,v);
527: if AbsVal(prev_t - t1) > tol
528: then x := Hermite(prev_t,t1,t,prev_x,x,prev_v,v);
529: end if;
530: end if;
531: end Hermite_Single_Real_Predictor;
532:
533: end Predictors;
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>