code 34444; procedure PEIDE(N,M,NOBS,NBP,PAR,RES,BP,JTJINV,IN,OUT,DERIV,JAC DFDY, JAC DFDP, CALL YSTART,DATA,MONITOR); value N,M,NOBS; integer N,M,NOBS,NBP; array PAR,RES,JTJINV,IN,OUT; integer array BP; procedure CALL YSTART,DATA,MONITOR; boolean procedure DERIV,JAC DFDY,JACDFDP; begin integer I,J,EXTRA,WEIGHT,NCOL,NROW,AWAY,NPAR,II,JJ,MAX, NFE,NIS; real EPS,EPS1,XEND,C,X,T,HMIN,HMAX,RES1,IN3,IN4,FAC3,FAC4; array AUX[1:3],OBS[1:NOBS],SAVE[-38:6*N],TOBS[0:NOBS], YP[1:NBP+NOBS,1:NBP+M],YMAX[1:N],Y[1:6*N*(NBP+M+1)],FY[1:N,1:N], FP[1:N,1:M+NBP]; integer array COBS[1:NOBS]; boolean FIRST,SEC,CLEAN; real procedure INTERPOL(STARTINDEX,JUMP,K,TOBSDIF); value STARTINDEX,JUMP,K,TOBSDIF; integer STARTINDEX,JUMP,K; real TOBSDIF; begin integer I; real S,R; S:=Y[STARTINDEX]; R:=TOBSDIF; for I:=1 step 1 until K do begin STARTINDEX:=STARTINDEX+JUMP; S:=S+Y[STARTINDEX]*R; R:=R*TOBSDIF end; INTERPOL:=S end INTERPOL; procedure JAC DYDP(NROW,NCOL,PAR,RES,JAC,LOCFUNCT); value NROW,NCOL; integer NROW,NCOL; array PAR,RES,JAC; procedure LOCFUNCT; begin DUPMAT(1,NROW,1,NCOL,JAC,YP) end JACOBIAN boolean procedure FUNCT(NROW,NCOL,PAR,RES); value NROW,NCOL; integer NROW,NCOL; array PAR,RES; begin integer L,K,KNEW,FAILS,SAME,KPOLD,N6,NNPAR,J5N, COBSII; real XOLD,HOLD,A0,TOLUP,TOL,TOLDWN,TOLCONV,H,CH,CHNEW, ERROR,DFI,TOBSDIF; boolean EVALUATE,EVALUATED,DECOMPOSE,CONV; array A[0:5],DELTA,LAST DELTA,DF,Y0[1:N],JACOB[1:N,1:N]; integer array P[1:N]; real procedure NORM2(AI); real AI; begin real S,A; S:= "-100; for I:= 1 step 1 until N do begin A:= AI/YMAX[I]; S:= S + A * A end; NORM2:= S end NORM2; procedure RESET; begin if CH < HMIN/HOLD then CH:= HMIN/HOLD else if CH > HMAX/HOLD then CH:= HMAX/HOLD; X:= XOLD; H:= HOLD * CH; C:= 1; for J:= 0 step N until K*N do begin for I:= 1 step 1 until N do Y[J+I]:= SAVE[J+I] * C; C:= C * CH end; DECOMPOSE:=true end RESET; procedure ORDER; begin C:= EPS * EPS; J:= (K-1) * (K + 8)/2 - 38; for I:= 0 step 1 until K do A[I]:= SAVE[I+J]; J:= J + K + 1; TOLUP := C * SAVE[J]; TOL := C * SAVE[J + 1]; TOLDWN := C * SAVE[J + 2]; TOLCONV:= EPS/(2 * N * (K + 2)); A0:= A[0]; DECOMPOSE:= true; end ORDER; procedure EVALUATE JACOBIAN; begin EVALUATE:= false; DECOMPOSE:= EVALUATED:= true; if not JAC DFDY(PAR,Y,X,FY) then begin SAVE[-3]:=4; goto RETURN end; end EVALUATE JACOBIAN procedure DECOMPOSE JACOBIAN; begin DECOMPOSE:= false; C:= -A0 * H; for J:= 1 step 1 until N do begin for I:= 1 step 1 until N do JACOB[I,J]:= FY[I,J] * C; JACOB[J,J]:= JACOB[J,J] + 1 end; DEC(JACOB,N,AUX,P) end DECOMPOSE JACOBIAN; procedure CALCULATE STEP AND ORDER; begin real A1,A2,A3; A1:= if K <= 1 then 0 else 0.75 * (TOLDWN/NORM2(Y[K*N+I])) ** (0.5/K); A2:= 0.80 * (TOL/ERROR) ** (0.5/(K + 1)); A3:= if K >= 5 or FAILS ^= 0 then 0 else 0.70 * (TOLUP/NORM2(DELTA[I] - LAST DELTA[I]))** (0.5/(K+2)); if A1 > A2 and A1 > A3 then begin KNEW:= K-1; CHNEW:= A1 end else if A2 > A3 then begin KNEW:= K ; CHNEW:= A2 end else begin KNEW:= K+1; CHNEW:= A3 end end CALCULATE STEP AND ORDER; if SEC then begin SEC:=false; goto RETURN end; NPAR:=M; EXTRA:=NIS:=0; II:=1; JJ:=if NBP=0 then 0 else 1; N6:=N*6; INIVEC(-3,-1,SAVE,0); INIVEC(N6+1,(6+M)*N,Y,0); INIMAT(1,NOBS+NBP,1,M+NBP,YP,0); T:=TOBS[1]; X:=TOBS[0]; CALL YSTART(PAR,Y,YMAX); HMAX:=TOBS[1]-TOBS[0]; HMIN:=HMAX*IN[1]; EVALUATE JACOBIAN; NNPAR:=N*NPAR; NEW START: K:= 1; KPOLD:=0; SAME:= 2; ORDER; if not DERIV(PAR,Y,X,DF) then begin SAVE[-3]:=3; goto RETURN end; H:=SQRT(2 * EPS/SQRT(NORM2 (MATVEC(1,N,I,FY,DF)))); if H > HMAX then H:= HMAX else if H < HMIN then H:= HMIN; XOLD:= X; HOLD:= H; CH:= 1; for I:= 1 step 1 until N do begin SAVE[I]:=Y[I]; SAVE[N+I]:=Y[N+I]:=DF[I]*H end; FAILS:= 0; for L:= 0 while X < XEND do begin if X + H <= XEND then X:= X + H else begin H:= XEND-X; X:= XEND; CH:= H/HOLD; C:= 1; for J:= N step N until K*N do begin C:= C* CH; for I:= J+1 step 1 until J+N do Y[I]:= Y[I] * C end; SAME:= if SAME<3 then 3 else SAME+1; end; comment PREDICTION; for L:= 1 step 1 until N do begin for I:= L step N until (K-1)*N+L do for J:= (K-1)*N+L step -N until I do Y[J]:= Y[J] + Y[J+N]; DELTA[L]:= 0 end; EVALUATED:= false; comment CORRECTION AND ESTIMATION LOCAL ERROR; for L:= 1,2,3 do begin if not DERIV(PAR,Y,X,DF) then begin SAVE[-3]:=3; goto RETURN end; for I:= 1 step 1 until N do DF[I]:= DF[I] * H - Y[N+I]; if EVALUATE then EVALUATE JACOBIAN; if DECOMPOSE then DECOMPOSE JACOBIAN; SOL(JACOB,N,P,DF); CONV:= true; for I:= 1 step 1 until N do begin DFI:= DF[I]; Y[ I]:= Y[ I] + A0 * DFI; Y[N+I]:= Y[N+I] + DFI; DELTA[I]:= DELTA[I] + DFI; CONV:= CONV and ABS(DFI) < TOLCONV * YMAX[I] end; if CONV then begin ERROR:= NORM2(DELTA[I]); goto CONVERGENCE end end; comment ACCEPTANCE OR REJECTION; if not CONV then begin if not EVALUATED then EVALUATE:= true else begin CH:=CH/4; if H<4*HMIN then begin SAVE[-1]:= SAVE[-1]+10; HMIN:=HMIN/10; if SAVE[-1]>40 then goto RETURN end end; RESET end else CONVERGENCE: if ERROR > TOL then begin FAILS:= FAILS + 1; if H > 1.1 * HMIN then begin if FAILS > 2 then begin RESET; goto NEW START end else begin CALCULATE STEP AND ORDER; if KNEW ^= K then begin K:= KNEW; ORDER end; CH:= CH * CHNEW; RESET end end else begin if K = 1 then begin comment VIOLATE EPS CRITERION; SAVE[-2]:= SAVE[-2] + 1; SAME:= 4; goto ERROR TEST OK end; K:=1; RESET; ORDER; SAME:= 2 end end else ERROR TEST OK: begin FAILS:= 0; for I:= 1 step 1 until N do begin C:= DELTA[I]; for L:= 2 step 1 until K do Y[L*N+I]:= Y[L*N+I] + A[L] * C; if ABS(Y[I]) > YMAX[I] then YMAX[I]:= ABS(Y[I]) end; SAME:= SAME-1; if SAME= 1 then DUPVEC(1,N,0,LAST DELTA,DELTA) else if SAME= 0 then begin CALCULATE STEP AND ORDER; if CHNEW > 1.1 then begin if K ^= KNEW then begin if KNEW > K then MULVEC(KNEW*N+1,KNEW*N+N,-KNEW*N,Y,DELTA, A[K]/KNEW); K:= KNEW; ORDER end; SAME:= K+1; if CHNEW * H > HMAX then CHNEW:= HMAX/H; H:= H * CHNEW; C:= 1; for J:= N step N until K*N do begin C:= C * CHNEW; MULVEC(J+1,J+N,0,Y,Y,C) end; DECOMPOSE:=true end else SAME:= 10 end OF A SINGLE INTEGRATION STEP OF Y; NIS:=NIS+1; comment START OF A INTEGRATION STEP OF YP; if CLEAN then begin HOLD:=H; XOLD:=X; KPOLD:=K; CH:=1; DUPVEC(1,K*N+N,0,SAVE,Y) end else begin if H^=HOLD then begin CH:=H/HOLD; C:=1; for J:=N6+NNPAR step NNPAR until KPOLD*NNPAR+N6 do begin C:=C*CH; for I:=J+1 step 1 until J+NNPAR do Y[I]:=Y[I]*C end; HOLD:=H end; if K>KPOLD then INIVEC(N6+K*NNPAR+1,N6+K*NNPAR+NNPAR,Y,0); XOLD:= X; KPOLD:= K; CH:= 1; DUPVEC(1,K*N+N,0,SAVE,Y); EVALUATE JACOBIAN; DECOMPOSE JACOBIAN; if not JAC DFDP(PAR,Y,X,FP) then begin SAVE[-3]:=5; goto RETURN end; if NPAR>M then INIMAT(1,N,M+1,NPAR,FP,0); comment PREDICTION; for L:=0 step 1 until K-1 do for J:=K-1 step -1 until L do ELMVEC(J*NNPAR+N6+1,J*NNPAR+N6+NNPAR,NNPAR,Y,Y,1); comment CORRECTION; for J:=1 step 1 until NPAR do begin J5N:=(J+5)*N; DUPVEC(1,N,J5N,Y0,Y); for I:=1 step 1 until N do DF[I]:= H*(FP[I,J]+MATVEC(1,N,I,FY,Y0)) -Y[NNPAR+J5N+I]; SOL(JACOB,N,P,DF); for L:=0 step 1 until K do begin I:=L*NNPAR+J5N; ELMVEC(I+1,I+N,-I,Y,DF,A[L]) end end end; for L:=0 while X>=T do begin comment CALCULATION OF A ROW OF THE JACOBIAN MATRIX AND AN ELEMENT OF THE RESIDUAL VECTOR; TOBSDIF:=(TOBS[II]-X)/H; COBSII:=COBS[II]; RES[II]:=INTERPOL(COBSII,N,K,TOBSDIF)-OBS[II]; if not CLEAN then begin for I:=1 step 1 until NPAR do YP[II,I]:=INTERPOL(COBSII+(I+5)*N,NNPAR,K, TOBSDIF); comment INTRODUCING OF BREAK-POINTS; if BP[JJ]^=II then else if FIRST and ABS(RES[II])<EPS1 then begin NBP:=NBP-1; comment DUPVEC(BP) ; for I:= JJ step 1 until NBP do BP[I]:= BP[I + 1]; BP[NBP+1]:=0 end else begin EXTRA:=EXTRA+1; if FIRST then PAR[M+JJ]:=OBS[II]; comment INTRODUCING A JACOBIAN ROW AND A RESIDUAL VECTOR ELEMENT FOR CONTINUITY REQUIREMENTS; YP[NOBS+JJ,M+JJ]:=-WEIGHT; MULROW(1,NPAR,NOBS+JJ,II,YP,YP,WEIGHT); RES[NOBS+JJ]:=WEIGHT*(RES[II]+OBS[II]- PAR[M+JJ]) end end; if II=NOBS then goto RETURN else begin T:=TOBS[II+1]; if BP[JJ]=II and JJ<NBP then JJ:=JJ+1; HMAX:=T-TOBS[II]; HMIN:=HMAX*IN[1]; II:=II+1 end; end; comment BREAK-POINTS INTRODUCE NEW INITIAL VALUES FOR Y AND YP; if EXTRA>0 then begin for I:=1 step 1 until N do begin Y[I]:=INTERPOL(I,N,K,TOBSDIF); for J:=1 step 1 until NPAR do Y[I+(J+5)*N]:=INTERPOL(I+(J+5)*N,NNPAR,K, TOBSDIF) end; for L:=1 step 1 until EXTRA do begin COBSII:=COBS[BP[NPAR-M+L]]; Y[COBSII]:=PAR[NPAR+L]; for I:=1 step 1 until NPAR+EXTRA do Y[COBSII+(5+I)*N]:=0; INIVEC(1+NNPAR+(L+5)*N,NNPAR+(L+6)*N,Y,0); Y[COBSII+(5+NPAR+L)*N]:=1 end; NPAR:=NPAR+EXTRA; EXTRA:=0; X:=TOBS[II-1]; EVALUATE JACOBIAN; NNPAR:=N*NPAR; goto NEW START end end end STEP; RETURN: if SAVE[-2]>MAX then MAX:=SAVE[-2]; FUNCT:=SAVE[-1]<=40 and SAVE[-3]=0; if not FIRST then MONITOR(1,NCOL,NROW,PAR,RES,WEIGHT,NIS) end FUNCT; I:= -39; for C:= 1,1,9,4,0,2/3,1,1/3,36,20.25,1,6/11, 1,6/11,1/11,84.028,53.778,0.25,.48,1,.7,.2,.02, 156.25, 108.51, .027778, 120/274, 1, 225/274, 85/274, 15/274, 1/274, 0, 187.69, .0047361 do begin I:= I + 1; SAVE[I]:= C end; DATA(NOBS,TOBS,OBS,COBS); WEIGHT:=1; FIRST:=SEC:=false; CLEAN:=NBP>0; AUX[2]:="-12; EPS:=IN[2]; EPS1:="10; XEND:=TOBS[NOBS]; OUT[1]:=0; BP[0]:=MAX:=0; comment SMOOTH INTEGRATION WITHOUT BREAK-POINTS; if not FUNCT(NOBS,M,PAR,RES) then goto ESCAPE; RES1:=SQRT(VECVEC(1,NOBS,0,RES,RES)); NFE:=1; if IN[5]=1 then begin OUT[1]:=1; goto ESCAPE end; if CLEAN then begin FIRST:=true; CLEAN:=false; FAC3:=SQRT(SQRT(IN[3]/RES1)); FAC4:=SQRT(SQRT(IN[4]/RES1)); EPS1:=RES1*FAC4; if not FUNCT(NOBS,M,PAR,RES) then goto ESCAPE; FIRST:=false end else NFE:=0; NCOL:=M+NBP; NROW:=NOBS+NBP; SEC:=true; IN3:=IN[3]; IN4:=IN[4]; IN[3]:=RES1; begin real W; array AID[1:NCOL,1:NCOL]; WEIGHT:=AWAY:=0; OUT[4]:=OUT[5]:=W:=0; for WEIGHT:=(SQRT(WEIGHT)+1)**2 while WEIGHT^=16 and NBP>0 do begin if AWAY=0 and W^=0 then begin comment IF NO BREAK-POINTS WERE OMITTED THEN ONE FUNCTION EVALUATION IS SAVED; W:=WEIGHT/W; for I:=NOBS+1 step 1 until NROW do begin for J:=1 step 1 until NCOL do YP[I,J]:=W*YP[I,J]; RES[I]:=W*RES[I] end; SEC:=true; NFE:=NFE-1 end; IN[3]:=IN[3]*FAC3*WEIGHT; IN[4]:=EPS1; MONITOR(2,NCOL,NROW,PAR,RES,WEIGHT,NIS); MARQUARDT(NROW,NCOL,PAR,RES,AID,FUNCT,JAC DYDP,IN,OUT); if OUT[1]>0 then goto ESCAPE; comment THE RELATIVE STARTING VALUE OF LAMBDA IS ADJUSTED TO THE LAST VALUE OF LAMBDA USED; AWAY:=OUT[4]-OUT[5]-1; IN[6]:=IN[6] * 5**AWAY * 2**(AWAY-OUT[5]); NFE:=NFE+OUT[4]; W:=WEIGHT; EPS1:=(SQRT(WEIGHT)+1)**2*IN[4]*FAC4; AWAY:=0; comment USELESS BREAK-POINTS ARE OMITTED; J:= 0; for J:= J + 1 while J le NBP do begin if ABS(OBS[BP[J]]+RES[BP[J]]-PAR[J+M])<EPS1 then begin NBP:=NBP-1; comment DUPVEC (BP) ; for I:= J step 1 until NBP do BP[I]:= BP[I + 1]; DUPVEC(J+M,NBP+M,1,PAR,PAR); J:=J-1; AWAY:=AWAY+1; BP[NBP+1]:=0 end end; NCOL:=NCOL-AWAY; NROW:=NROW-AWAY end; IN[3]:=IN3; IN[4]:=IN4; NBP:=0; WEIGHT:=1; MONITOR(2,M,NOBS,PAR,RES,WEIGHT,NIS); MARQUARDT(NOBS,M,PAR,RES,JTJINV,FUNCT,JAC DYDP,IN,OUT); NFE:=OUT[4]+NFE end; ESCAPE: if OUT[1]=3 then OUT[1]:=2 else if OUT[1]=4 then OUT[1]:=6; if SAVE[-3]^=0 then OUT[1]:=SAVE[-3]; OUT[3]:=RES1; OUT[4]:=NFE; OUT[5]:=MAX end PEIDE; eop