summaryrefslogtreecommitdiff
path: root/Utilib/src/ALTERP.f
blob: 379a3fd73bcdc9248ba8be80a313f2a863bd5c72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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