code 33135; procedure IMPEX (N, T0, TEND, Y0, DERIV, AVAILABLE, H0, HMAX, PRESCH, EPS, WEIGHTS, UPDATE, FAIL, CONTROL); value N; integer N; real T0,TEND,H0,HMAX,EPS; boolean PRESCH,FAIL; array Y0,WEIGHTS; boolean procedure AVAILABLE; procedure DERIV,UPDATE,CONTROL; begin integer I,K,ECI; real T,T1,T2,T3,TP,H,H2,HNEW,ALF,LQ; array Y,Z,S1,S2,S3,U1,U3,W1,W2,W3,EHR[1:N],R,RF[1:5,1:N], ERR[1:3],A1,A2[1:N,1:N]; integer array PS1,PS2[1:N]; boolean START,TWO,HALV; procedure DFDY(T,Y,A); real T; array Y,A; begin integer I,J; real SL; array F1,F2[1:N]; DERIV(T,Y,F1,N); for I:=1 step 1 until N do begin SL:="-6*Y[I]; if ABS(SL)<"-6 then SL:="-6; Y[I]:=Y[I]+SL; DERIV(T,Y,F2,N); for J:=1 step 1 until N do A[J,I]:=(F2[J]-F1[J])/SL; Y[I]:=Y[I]-SL; end end DFDY; procedure STARTV(Y,T); value T; real T; array Y; begin real A,B,C; A:=(T-T1)/(T1-T2); B:=(T-T2)/(T1-T3); C:=(T-T1)/(T2-T3)*B; B:=A*B; A:=1+A+B; B:=A+C-1; MULVEC(1,N,0,Y,S1,A); ELMVEC(1,N,0,Y,S2,-B); ELMVEC(1,N,0,Y,S3,C) end STARTV procedure ITERATE(Z,Y,A,H,T,WEIGHTS,FAIL,PS); array Z,Y,A,WEIGHTS; real H,T; label FAIL; integer array PS; begin integer IT,LIT; real MAX,MAX1,CONV; array DZ,F1[1:N]; for I:=1 step 1 until N do Z[I]:=(Z[I]+Y[I])/2; IT:=LIT:=1; CONV:=1; ATER: DERIV(T,Z,F1,N); for I:=1 step 1 until N do F1[I]:=DZ[I]:=Z[I]-H*F1[I]/2-Y[I]; SOL(A,N,PS,DZ); ELMVEC(1,N,0,Z,DZ,-1); MAX:=0; for I:=1 step 1 until N do MAX:=MAX+(WEIGHTS[I]*DZ[I])**2; MAX:=SQRT(MAX); if MAX*CONV<EPS/10 then goto OUT; IT:=IT+1; if IT=2 then goto ASS; CONV:=MAX/MAX1; if CONV>.2 then begin if LIT=0 then goto FAIL; LIT:=0; CONV:=1; IT:=1; RECOMP(A,H,T,Z,FAIL,PS); end; ASS: MAX1:=MAX; goto ATER; OUT: for I:=1 step 1 until N do Z[I]:=2*Z[I]-Y[I]; end ITERATE; procedure RECOMP(A,H,T,Y,FAIL,PS); real H,T; array A,Y; label FAIL; integer array PS; begin real SL; array AUX[1:3]; SL:=H/2; if not AVAILABLE(T,Y,A,N) then DFDY(T,Y,A); for I:=1 step 1 until N do begin MULROW(1,N,I,I,A,A,-SL); A[I,I]:=1+A[I,I] end; AUX[2]:="-14; DEC(A,N,AUX,PS); if AUX[3]<N then goto FAIL end RECOMP; procedure INITIALIZATION; begin H2:=HNEW; H:=H2/2; DUPVEC(1,N,0,S1,Y0); DUPVEC(1,N,0,S2,Y0); DUPVEC(1,N,0,S3,Y0); DUPVEC(1,N,0,W1,Y0); DUPROWVEC(1,N,1,R,Y0); INIVEC(1,N,U1,0); INIVEC(1,N,W2,0); INIMAT(2,5,1,N,R,0); INIMAT(1,5,1,N,RF,0); T:=T1:=T0; T2:=T0-2*H-"6; T3:=2*T2+1; RECOMP(A1,H,T,S1,MISS,PS1);RECOMP(A2,H2,T,W1,MISS,PS2); end procedure ONE LARGE STEP; begin STARTV(Z,T+H); ITERATE(Z,S1,A1,H,T+H/2,WEIGHTS,MISS,PS1); DUPVEC(1,N,0,Y,Z); STARTV(Z,T+H2); ITERATE(Z,Y,A1,H,T+3*H/2,WEIGHTS,MISS,PS1); DUPVEC(1,N,0,U3,U1); DUPVEC(1,N,0,U1,Y); DUPVEC(1,N,0,S3,S2); DUPVEC(1,N,0,S2,S1); DUPVEC(1,N,0,S1,Z); ELMVEC(1,N,0,Z,W1,1); ELMVEC(1,N,0,Z,S2,-1); ITERATE(Z,W1,A2,H2,T+H,WEIGHTS,MISS,PS2); T3:=T2; T2:=T1; T1:=T+H2; DUPVEC(1,N,0,W3,W2); DUPVEC(1,N,0,W2,W1); DUPVEC(1,N,0,W1,Z); end; procedure CHANGE OF INFORMATION; begin real ALF1,C1,C2,C3; array KOF[2:4,2:4],E,D[1:4]; integer I, K; C1:=HNEW/H2; C2:=C1*C1; C3:=C2*C1; KOF[2,2]:=C1; KOF[2,3]:=(C1-C2)/2; KOF[2,4]:=C3/6-C2/2+C1/3; KOF[3,3]:=C2; KOF[3,4]:=C2-C3; KOF[4,4]:=C3; for I:=1 step 1 until N do U1[I]:=R[2,I]+R[3,I]/2+R[4,I]/3; ALF1:=MATVEC(1,N,1,RF,U1)/VECVEC(1,N,0,U1,U1); ALF:=(ALF+ALF1)*C1; for I:=1 step 1 until N do begin E[1]:=RF[1,I]-ALF1*U1[I]; E[2]:=RF[2,I]-ALF1*2*R[3,I]; E[3]:=RF[3,I]-ALF1*4*R[4,I]; E[4]:=RF[4,I]; D[1]:=R[1,I]; RF[1,I]:=E[1]:=E[1]*C2; for K:=2 step 1 until 4 do begin R[K,I]:=D[K]:=MATMAT(K,4,K,I,KOF,R); RF[K,I]:=E[K]:=C2*MATVEC(K,4,K,KOF,E) end K; S1[I]:=D[1]+E[1];W1[I]:=D[1]+4*E[1]; S2[I]:=S1[I]-(D[2]+E[2]/2); S3[I]:=S2[I]-(D[2]+E[2])+(D[3]+E[3]/2); end I; T3:=T-HNEW; T2:=T-HNEW/2; T1:=T; H2:=HNEW; H:=H2/2; ERR[1]:=0; if HALV then begin for I:=1 step 1 until N do PS2[I]:= PS1[I]; DUPMAT(1,N,1,N,A2,A1) end; if TWO then begin for I:=1 step 1 until N do PS1[I]:= PS2[I]; DUPMAT(1,N,1,N,A1,A2) end else RECOMP(A1,HNEW/2,T,S1,MISS,PS1); if ^HALV then RECOMP(A2,HNEW,T,W1,MISS,PS2); end HNEW^=H2 procedure BACKWARD DIFFERENCES; for I:=1 step 1 until N do begin real B0,B1,B2,B3; B1:=(U1[I]+2*S2[I]+U3[I])/4; B2:=(W1[I]+2*W2[I]+W3[I])/4; B3:=(S3[I]+2*U3[I]+S2[I])/4; B2:=(B2-B1)/3; B0:=B1-B2; B2:=B2-(S1[I]-2*S2[I]+S3[I])/16; B1:=2*B3-(B2+RF[1,I])-(B0+R[1,I])/2; B3:=0; for K:=1 step 1 until 4 do begin B1:=B1-B3; B3:=R[K,I]; R[K,I]:=B0; B0:=B0-B1 end; R[5,I]:=B0; for K:=1 step 1 until 4 do begin B3:=RF[K,I]; RF[K,I]:=B2; B2:=B2-B3 end; RF[5,I]:=B2; end; procedure ERROR ESTIMATES; begin real C0,C1,C2,C3,B0,B1,B2,B3,W,SL1,SN,LR; C0:=C1:=C2:=C3:=0; for I:=1 step 1 until N do begin W:=WEIGHTS[I]**2; B0:=RF[4,I]/36; C0:=C0+B0*B0*W; LR:=ABS(B0); B1:=RF[1,I]+ALF*R[2,I]; C1:=C1+B1*B1*W; B2:=RF[3,I]; C2:=C2+B2*B2*W; SL1:=ABS(RF[1,I]-RF[2,I]); SN:=if SL1<"-10 then 1else ABS(RF[1,I]-R[4,I]/6)/SL1; if SN>1 then SN:=1; if START then begin SN:=SN**4; LR:=LR*4 end; EHR[I]:=B3:=SN*EHR[I]+LR; C3:=C3+B3*B3*W; end I; B0:=ERR[1]; ERR[1]:=B1:=SQRT(C0); ERR[2]:=SQRT(C1); ERR[3]:=SQRT(C3)+SQRT(C2)/2; LQ:=EPS/(if B0<B1 then B1"ELSE" B0); if B0<B1 and LQ>=80 then LQ:=10; end; procedure REJECT; if START then begin HNEW:=LQ**(1/5)*H/2; goto INIT end else begin for K:=1,2,3,4,1,2,3 do ELMROW(1,N,K,K+1,R,R,-1); for K:=1,2,3,4 do ELMROW(1,N,K,K+1,RF,RF,-1); T:=T-H2; HALV:=true; HNEW:=H; goto MSTP end procedure STEPSIZE; if LQ<2 then begin HALV:=true; HNEW:=H end else begin if LQ>80 then HNEW:=(if LQ>5120 then (LQ/5)**(1/5) else 2)*H2; if HNEW>HMAX then HNEW:=HMAX; if TEND>T and TEND-T<HNEW then HNEW:=TEND-T; TWO:=HNEW=2*H2; end; if PRESCH then H:=H0 else begin if H0>HMAX then H:=HMAX else H:=H0; if H>(TEND-T0)/4 then H:=(TEND-T0)/4; end; HNEW:=H; ALF:=0; T:=TP:=T0; INIVEC(1,3,ERR,0); INIVEC(1,N,EHR,0); DUPROWVEC(1,N,1,R,Y0); INIMAT(2, 5, 1, N, R, 0.0); CONTROL(TP,T,H,HNEW,R,ERR,N); INIT: INITIALIZATION; START:=true; for ECI:=0,1,2,3 do begin ONE LARGE STEP; T:=T+H2; if ECI>0 then begin BACKWARD DIFFERENCES; UPDATE(WEIGHTS,S2,N) end end; ECI:=4; MSTP: if HNEW^=H2 then begin ECI:=1; CHANGE OF INFORMATION; ONE LARGE STEP; T:=T+H2; ECI:=2; end; ONE LARGE STEP; BACKWARD DIFFERENCES; UPDATE(WEIGHTS,S2,N); ERROR ESTIMATES; if ECI<4 and LQ>80 then LQ:=20; HALV:=TWO:=false; if PRESCH then goto TRYCK; if LQ<1 then REJECT else STEPSIZE; TRYCK: if TP<=T then CONTROL(TP,T,H,HNEW,R,ERR,N); if START then START:=false; if HNEW=H2 then T:=T+H2; ECI:=ECI+1; if T<TEND+H2 then goto MSTP else goto END; MISS: FAIL:=PRESCH; if ^ FAIL then begin if ECI>1 then T:=T-H2; HALV:=TWO:=false; HNEW:=H2/2; if START then goto INIT else goto TRYCK end; END: end IMPEX; eop