diff options
Diffstat (limited to 'Utilib/src/ALTERP.f')
| -rw-r--r-- | Utilib/src/ALTERP.f | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/Utilib/src/ALTERP.f b/Utilib/src/ALTERP.f new file mode 100644 index 0000000..379a3fd --- /dev/null +++ b/Utilib/src/ALTERP.f @@ -0,0 +1,172 @@ +*DECK ALTERP + SUBROUTINE ALTERP(LCUBIC,N,X,VAL,LDERIV,TERP) +* +*----------------------------------------------------------------------- +* +*Purpose: +* determination of the TERP interpolation/derivation components using +* the order 4 Ceschino method with cubic Hermite polynomials. +* +*Copyright: +* Copyright (C) 2006 Ecole Polytechnique de Montreal +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; either +* version 2.1 of the License, or (at your option) any later version +* +*Author(s): A. Hebert +* +*Parameters: input +* LCUBIC =.TRUE.: cubic Ceschino interpolation; =.FALSE: linear +* Lagrange interpolation. +* N number of points. +* X abscissas +* VAL abscissa of the interpolated point. +* LDERIV set to .true. to compute the first derivative with respect +* to X. Set to .false. to interpolate. +* +*Parameters: output +* TERP interpolation/derivation components. +* +*----------------------------------------------------------------------- +* +*---- +* SUBROUTINE ARGUMENTS +*---- + INTEGER N + LOGICAL LCUBIC,LDERIV + REAL X(N),VAL,TERP(N) +*--- +* LOCAL VARIABLES +*--- + CHARACTER HSMG*131 + REAL, ALLOCATABLE, DIMENSION(:,:) :: WK +* + I0=0 + IF(N.LE.1) CALL XABORT('ALTERP: INVALID NUMBER OF POINTS.') + IF(N.EQ.2) GO TO 110 + DO 10 I=1,N + TERP(I)=0.0 + 10 CONTINUE +*---- +* INTERVAL IDENTIFICATION. +*---- + DO 20 I=1,N-1 + IF((VAL.GE.X(I)).AND.(VAL.LE.X(I+1))) THEN + I0=I + GO TO 30 + ENDIF + 20 CONTINUE + WRITE(HSMG,'(35HALTERP: UNABLE TO INTERPOLATE (VAL=,1P,E11.4, + 1 8H LIMITS=,E11.4,2H, ,E11.4,2H).)') VAL,X(1),X(N) + CALL XABORT(HSMG) + 30 DX=X(I0+1)-X(I0) +*---- +* LINEAR LAGRANGE POLYNOMIAL. +*---- + IF(.NOT.LCUBIC) THEN + IF(LDERIV) THEN + TERP(I0)=-1.0/DX + TERP(I0+1)=1.0/DX + ELSE + TERP(I0)=(X(I0+1)-VAL)/DX + TERP(I0+1)=1.0-TERP(I0) + ENDIF + RETURN + ENDIF +*---- +* CESCHINO CUBIC POLYNOMIAL. +*---- + ALLOCATE(WK(3,N)) + DO 35 I=1,N + WK(3,I)=0.0 + 35 CONTINUE + U=(VAL-0.5*(X(I0)+X(I0+1)))/DX + IF(LDERIV) THEN + H1=(-6.0*(0.5-U)+6.0*(0.5-U)**2)/DX + H2=(-2.0*(0.5-U)+3.0*(0.5-U)**2)/DX + H3=(6.0*(0.5+U)-6.0*(0.5+U)**2)/DX + H4=(-2.0*(0.5+U)+3.0*(0.5+U)**2)/DX + TEST=0.0 + ELSE + H1=3.0*(0.5-U)**2-2.0*(0.5-U)**3 + H2=(0.5-U)**2-(0.5-U)**3 + H3=3.0*(0.5+U)**2-2.0*(0.5+U)**3 + H4=-(0.5+U)**2+(0.5+U)**3 + TEST=1.0 + ENDIF + TERP(I0)=H1 + TERP(I0+1)=H3 + WK(3,I0)=H2*DX + WK(3,I0+1)=H4*DX +*---- +* COMPUTE THE COEFFICIENT MATRIX. +*---- + HP=1.0/(X(2)-X(1)) + WK(1,1)=HP + WK(2,1)=HP + DO 40 I=2,N-1 + HM=HP + HP=1.0/(X(I+1)-X(I)) + WK(1,I)=2.0*(HM+HP) + WK(2,I)=HP + 40 CONTINUE + WK(1,N)=HP + WK(2,N)=HP +*---- +* FORWARD ELIMINATION. +*---- + PMX=WK(1,1) + WK(3,1)=WK(3,1)/PMX + DO 50 I=2,N + GAR=WK(2,I-1) + WK(2,I-1)=WK(2,I-1)/PMX + PMX=WK(1,I)-GAR*WK(2,I-1) + WK(3,I)=(WK(3,I)-GAR*WK(3,I-1))/PMX + 50 CONTINUE +*---- +* BACK SUBSTITUTION. +*---- + DO 60 I=N-1,1,-1 + WK(3,I)=WK(3,I)-WK(2,I)*WK(3,I+1) + 60 CONTINUE +*---- +* COMPUTE THE INTERPOLATION FACTORS. +*---- + DO 100 J=1,N + IMIN=MAX(2,J-1) + IMAX=MIN(N-1,J+1) + DO 70 I=1,N + WK(1,I)=0.0 + 70 CONTINUE + WK(1,J)=1.0 + HP=1.0/(X(IMIN)-X(IMIN-1)) + YLAST=WK(1,IMIN-1) + WK(1,IMIN-1)=2.0*HP*HP*(WK(1,IMIN)-WK(1,IMIN-1)) + DO 80 I=IMIN,IMAX + HM=HP + HP=1.0/(X(I+1)-X(I)) + PMX=3.0*(HM*HM*(WK(1,I)-YLAST)+HP*HP*(WK(1,I+1)-WK(1,I))) + YLAST=WK(1,I) + WK(1,I)=PMX + 80 CONTINUE + WK(1,IMAX+1)=2.0*HP*HP*(WK(1,IMAX+1)-YLAST) + DO 90 I=IMIN-1,IMAX+1 + TERP(J)=TERP(J)+WK(1,I)*WK(3,I) + 90 CONTINUE + IF(ABS(TERP(J)).LE.1.0E-7) TERP(J)=0.0 + TEST=TEST-TERP(J) + 100 CONTINUE + IF(ABS(TEST).GT.1.0E-5) CALL XABORT('ALTERP: WRONG TERP FACTORS.') + DEALLOCATE(WK) + RETURN +* + 110 IF(LDERIV) THEN + TERP(1)=-1.0/(X(2)-X(1)) + TERP(2)=1.0/(X(2)-X(1)) + ELSE + TERP(1)=(X(2)-VAL)/(X(2)-X(1)) + TERP(2)=1.0-TERP(1) + ENDIF + RETURN + END |
