summaryrefslogtreecommitdiff
path: root/Utilib/src/ALTERP.f
diff options
context:
space:
mode:
authorstainer_t <thomas.stainer@oecd-nea.org>2025-09-08 13:48:49 +0200
committerstainer_t <thomas.stainer@oecd-nea.org>2025-09-08 13:48:49 +0200
commit7dfcc480ba1e19bd3232349fc733caef94034292 (patch)
tree03ee104eb8846d5cc1a981d267687a729185d3f3 /Utilib/src/ALTERP.f
Initial commit from Polytechnique Montreal
Diffstat (limited to 'Utilib/src/ALTERP.f')
-rw-r--r--Utilib/src/ALTERP.f172
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