V3FIT
linear1_mod.f90
1 MODULE linear1_mod
2 !-------------------------------------------------------------------------------
3 !LINEAR1-LINEAR interpolation in 1d
4 !
5 !LINEAR1_MOD is an F90 module of linear interpolating routines in 1d
6 !
7 !References:
8 !
9 ! W.A.Houlberg, F90 free format 8/2004
10 !
11 !Contains PUBLIC routines:
12 !
13 ! LINEAR1_INTERP -interpolate from one grid to another
14 ! LINEAR1_INTEG -integrate the linear fit
15 !
16 !Comments:
17 !
18 ! Linear interpolation routines are C0 (only f is continuous)
19 !
20 ! The modernization of the code structure into an F90 module takes advantage of
21 ! some of the more attractive features of F90:
22 ! -use of KIND for precision declarations
23 ! -optional arguments for I/O
24 ! -generic names for all intrinsic functions
25 ! -compilation using either free or fixed form
26 ! -no common blocks or other deprecated Fortran features
27 ! -dynamic and automatic alocation of variables
28 ! -array syntax for vector operations
29 !-------------------------------------------------------------------------------
30 USE spec_kind_mod
31 IMPLICIT NONE
32 
33 !-------------------------------------------------------------------------------
34 ! Public procedures
35 !-------------------------------------------------------------------------------
36 CONTAINS
37 
38 SUBROUTINE linear1_interp(n0,x0,y0,n1,x1, &
39  y1,iflag,message)
40 !-------------------------------------------------------------------------------
41 !W_LIN_INTERP performs a linear interpolation from the x0 mesh to the x1 mesh
42 !
43 !References:
44 ! W.A.Houlberg, F90 free format 8/2004
45 !
46 !Comments:
47 ! If the target mesh is outside the domain of the input mesh, the end data
48 ! value is returned
49 !-------------------------------------------------------------------------------
50 
51 !Declaration of input variables
52 INTEGER, INTENT(IN) :: &
53  n0, & !number of source abscissas [-]
54  n1 !number of target abscissas [-]
55 
56 REAL(KIND=rspec), INTENT(IN) :: &
57  x0(:), & !source abscissas (in increasing order) [arb]
58  x1(:), & !target abscissas [arb]
59  y0(:) !source values [arb]
60 
61 !Declaration of output variables
62 CHARACTER(len=*), INTENT(OUT) :: &
63  message !warning or error message [character]
64 
65 INTEGER, INTENT(OUT) :: &
66  iflag !error and warning flag [-]
67  !=-1 warning
68  !=0 none
69  !=1 error
70 
71 REAL(KIND=rspec), INTENT(OUT) :: &
72  y1(:) !target values [arb]
73 
74 !-------------------------------------------------------------------------------
75 !Declaration of local variables
76 INTEGER :: &
77  i,il
78 
79 !-------------------------------------------------------------------------------
80 !Initialization
81 !-------------------------------------------------------------------------------
82 !If no target values are requested, return
83 IF(n1 <= 0) THEN
84 
85  iflag=-1
86  message='LINEAR1_INTERP/WARNING(1):no points in output array'
87  GOTO 9999
88 
89 ENDIF
90 
91 !Make sure there are at least two nodes in the input grid
92 IF(n0 < 2) THEN
93 
94  iflag=1
95  message='LINEAR1_INTERP/ERROR(2):<2 points in source array'
96  GOTO 9999
97 
98 ENDIF
99 
100 !Set starting index of source grid
101 il=1
102 
103 !-------------------------------------------------------------------------------
104 !Interpolate from x0 to x1
105 !-------------------------------------------------------------------------------
106 DO i=1,n1 !Over index of target grid
107 
108  10 IF(x1(i) < x0(1)) THEN
109 
110  !Target is below data range, use innermost data value
111  y1(i)=y0(1)
112  iflag=-1
113  message='LINEAR1_INTERP(3)/WARNING:x<x(1), use end point'
114 
115  ELSEIF(x1(i) == x0(1)) THEN
116 
117  !Target and source nodes coincide
118  y1(i)=y0(1)
119 
120  ELSEIF(x1(i) > x0(il+1)) THEN
121 
122  !Beyond next source node
123  !Step x0 grid forward and loop
124  IF(il < n0-1) THEN
125 
126  il=il+1
127  GOTO 10
128 
129  ELSE
130 
131  !Target is above data range, set to last value
132  y1(i)=y0(n0)
133  iflag=-1
134  message='LINEAR1_INTERP(4)/WARNING:x>x(n0), use end point'
135 
136  ENDIF
137 
138  ELSE
139 
140  !Between the proper set of source nodes, interpolate
141  y1(i)=y0(il)+(y0(il+1)-y0(il))*(x1(i)-x0(il))/(x0(il+1)-x0(il))
142 
143  ENDIF
144 
145 ENDDO !Over index of target grid
146 
147 !-------------------------------------------------------------------------------
148 !Cleanup and exit
149 !-------------------------------------------------------------------------------
150 9999 CONTINUE
151 
152 END SUBROUTINE linear1_interp
153 
154 SUBROUTINE linear1_integ(k_order,n0,x0,f,n1,x1, &
155  value,iflag,message)
156 !-------------------------------------------------------------------------------
157 !LINEAR1_INTEG evaluates the integral f(x)*x**k_order, where f(x) is a linear
158 ! function and k_order is 0 or 1
159 !
160 !References:
161 ! W.A.Houlberg, F90 free format 8/2004
162 !-------------------------------------------------------------------------------
163 
164 !Declaration of input variables
165 INTEGER, INTENT(IN) :: &
166  k_order, & !exponent of weighting factor (s(x)*x**k_order) [-]
167  !=0 or 1 only
168  n0, & !number of source abcissas [-]
169  n1 !number of output abcissas (may be 1) [-]
170 
171 REAL(KIND=rspec), INTENT(IN) :: &
172  f(:), & !source ordinates [arb]
173  x0(:), & !source abcissas [arb]
174  x1(:) !output abcissas [arb]
175 
176 !Declaration of output variables
177 CHARACTER(len=*), INTENT(OUT) :: &
178  message !warning or error message [character]
179 
180 INTEGER, INTENT(OUT) :: &
181  iflag !error and warning flag [-]
182  !=-1 warning
183  !=0 none
184  !=1 error
185 
186 REAL(KIND=rspec), INTENT(OUT) :: &
187  value(:) !integral of f(x)*x**k_order from x0(1) to x1(i) [arb]
188 
189 !-------------------------------------------------------------------------------
190 !Declaration of local variables
191 INTEGER :: &
192  i,j,ido,jdo
193 
194 REAL(KIND=rspec) :: &
195  add,dx,f2,sum,xnew,xold
196 
197 !-------------------------------------------------------------------------------
198 !Initialization
199 !-------------------------------------------------------------------------------
200 !If no target values are requested, return
201 IF(n1 <= 0) THEN
202 
203  iflag=-1
204  message='LINEAR1_INTEG(1)/WARNING:no target points'
205  GOTO 9999
206 
207 ENDIF
208 
209 !If first target point is below range, return
210 IF(x1(1) < 0.99999_rspec*x0(1)) THEN
211 
212  iflag=1
213  message='LINEAR1_INTEG(2)/WARNING:target below range'
214  GOTO 9999
215 
216 ENDIF
217 
218 !If first target point is above range, return
219 IF(x1(n1) > 1.00001_rspec*x0(n0)) THEN
220 
221  iflag=1
222  message='LINEAR1_INTEG(3)/WARNING:target above range'
223  GOTO 9999
224 
225 ENDIF
226 
227 value(1:n1)=0
228 
229 !Integral value
230 sum=0
231 
232 !Source node, value and derivative
233 j=1
234 xold=x0(j)
235 f2=(f(2)-f(1))/(x0(2)-x0(1))
236 
237 !-------------------------------------------------------------------------------
238 !Integrate over target nodes
239 !-------------------------------------------------------------------------------
240 DO i=1,n1 !Over target nodes
241 
242 !Find dx to next source or target nodes
243  ido=0
244 
245  DO WHILE(ido == 0) !Over source nodes
246 
247  IF(x1(i) < x0(j+1)) THEN
248 
249  !Hit target nodes
250  xnew=x1(i)
251  ido=1
252  jdo=0
253 
254  ELSEIF(x1(i) == x0(j+1)) THEN
255 
256  !Hit both source and target nodes
257  xnew=x1(i)
258  ido=1
259  jdo=1
260 
261  ELSEIF(x1(i) > x0(j+1)) THEN
262 
263  !Hit source nodes
264  xnew=x0(j+1)
265  ido=0
266  jdo=1
267 
268  ENDIF
269 
270 !Integrate over dx
271  dx=xnew-xold
272 
273  IF(k_order == 1) THEN
274 
275  !Integral x s(x)dx
276  add=dx*(xold*f(j)+dx*((xold*f2+f(j))/2))
277 
278  ELSE
279 
280  !Integral s(x)dx
281  add=dx*(f(j)+dx*f2/2)
282 
283  ENDIF
284 
285 !Add increment and update endpoint
286  sum=sum+add
287  xold=xnew
288 
289  IF(jdo == 1) THEN
290 
291  !Increment source node and derivative
292  j=j+1
293 
294  IF(j == n0) THEN
295 
296  j=n0-1
297  f2=0
298 
299  ELSE
300 
301  f2=(f(j+1)-f(j))/(x0(j+1)-x0(j))
302 
303  ENDIF
304 
305  ENDIF
306 
307 !Set integral value
308  value(i)=sum
309 
310  ENDDO !Over source nodes
311 
312 ENDDO !Over target nodes
313 
314 !-------------------------------------------------------------------------------
315 !Cleanup and exit
316 !-------------------------------------------------------------------------------
317 9999 CONTINUE
318 
319 END SUBROUTINE linear1_integ
320 
321 END MODULE linear1_mod