ETS  \$Id: Doxyfile 2162 2020-02-26 14:16:09Z g2dpc $
 All Classes Files Functions Variables Pages
mod_interpolation.f90
Go to the documentation of this file.
2 
3  use itm_types
4 
5  implicit none
6 
7  contains
8 
9 !-----------------------------------------------------------------------------
10  subroutine interpolation(type_interp, xn1, xn2, xn3, xn4, r, s, x, xr, xs, &
11  xrs, xrr, xss, yn1, yn2, yn3, yn4, pn1, pn2, pn3, pn4, yr, ys, ps)
12 !-----------------------------------------------------------------------------
13 ! subroutine calculates the interpolated value of the function x given
14 ! by xi(1..4) at the four nodes using bi-cubic hermite elements
15 !
16 ! input:
17 ! type_interp
18 ! 0 : function value
19 ! 1 : funct. value + 1st derivatives
20 ! 2 : funct. value + 1st and 2nd derivatives
21 ! 3 : funct. value + 1st derivatives + yr, ys, ps
22 ! xn1, xn2, xn3, xn4
23 ! r, s
24 ! optional: yn1, yn2, yn3, yn4, pn1, pn2, pn3, pn4 (type_interp = 3)
25 !
26 ! output:
27 ! x
28 ! optional: xr, xs, xs, xrs, xrr, xss, yr, ys, ps
29 !-----------------------------------------------------------------------------
30 
31  real(r8), dimension(4), intent(in) :: xn1, xn2, xn3, xn4
32  real(r8), dimension(4), intent(in), optional :: yn1, yn2, yn3, yn4
33  real(r8), dimension(4), intent(in), optional :: pn1, pn2, pn3, pn4
34  real(r8), intent(in) :: r, s
35  integer(itm_i4), intent(in) :: type_interp
36 
37  real(r8), intent(out) :: x
38  real(r8), intent(out), optional :: xr, xs
39  real(r8), intent(out), optional :: xrs, xrr, xss
40  real(r8), intent(out), optional :: yr, ys, ps
41 
42  real(r8) :: hi0m, hri0m, hrri0m, hi1m, hri1m, hrri1m
43  real(r8) :: hj0m, hsj0m, hssj0m, hj1m, hsj1m, hssj1m
44  real(r8) :: hi0p, hri0p, hrri0p, hi1p, hri1p, hrri1p
45  real(r8) :: hj0p, hsj0p, hssj0p, hj1p, hsj1p, hssj1p
46 
47  hi0m = -(r - 1._r8)**2 * (-r - 2._r8) * 0.25_r8
48  hi1m = -(r - 1._r8)**2 * (-r - 1._r8) * 0.25_r8
49 
50  hj0m = -(s - 1._r8)**2 * (-s - 2._r8) * 0.25_r8
51  hj1m = -(s - 1._r8)**2 * (-s - 1._r8) * 0.25_r8
52 
53  hi0p = -(r + 1._r8)**2 * (r - 2._r8) * 0.25_r8
54  hi1p = (r + 1._r8)**2 * (r - 1._r8) * 0.25_r8
55 
56  hj0p = -(s + 1._r8)**2 * (s - 2._r8) * 0.25_r8
57  hj1p = (s + 1._r8)**2 * (s - 1._r8) * 0.25_r8
58 
59  x = hi0m * hj0m * xn1(1) + hi1m * hj0m * xn1(2) &
60  + hi0m * hj1m * xn1(3) + hi1m * hj1m * xn1(4) &
61  + hi0m * hj0p * xn2(1) + hi1m * hj0p * xn2(2) &
62  + hi0m * hj1p * xn2(3) + hi1m * hj1p * xn2(4) &
63  + hi0p * hj0m * xn4(1) + hi1p * hj0m * xn4(2) &
64  + hi0p * hj1m * xn4(3) + hi1p * hj1m * xn4(4) &
65  + hi0p * hj0p * xn3(1) + hi1p * hj0p * xn3(2) &
66  + hi0p * hj1p * xn3(3) + hi1p * hj1p * xn3(4)
67 
68  if (type_interp == 0) return
69 
70  hri0m = -(r - 1._r8) * (-r - 2._r8) * 0.5_r8 &
71  + (r - 1._r8)**2 * 0.25_r8
72  hri1m = -(r - 1._r8) * (-r - 1._r8) * 0.5_r8 &
73  + (r - 1._r8)**2 * 0.25_r8
74 
75  hsj0m = -(s - 1._r8) * (-s - 2._r8) * 0.5_r8 &
76  + (s - 1._r8)**2 * 0.25_r8
77  hsj1m = -(s - 1._r8) * (-s - 1._r8) * 0.5_r8 &
78  + (s - 1._r8)**2 * 0.25_r8
79 
80  hri0p = -(r + 1._r8) * (r - 2._r8) * 0.5_r8 - (r + 1._r8)**2 &
81  * 0.25_r8
82  hri1p = (r + 1._r8) * (r - 1._r8) * 0.5_r8 + (r + 1._r8)**2 &
83  * 0.25_r8
84 
85  hsj0p = -(s + 1._r8) * (s - 2._r8) * 0.5_r8 - (s + 1._r8)**2 &
86  * 0.25_r8
87  hsj1p = (s + 1._r8) * (s - 1._r8) * 0.5_r8 + (s + 1._r8)**2 &
88  * 0.25_r8
89 
90  xr = hri0m * hj0m * xn1(1) + hri1m * hj0m * xn1(2) &
91  + hri0m * hj1m * xn1(3) + hri1m * hj1m * xn1(4) &
92  + hri0m * hj0p * xn2(1) + hri1m * hj0p * xn2(2) &
93  + hri0m * hj1p * xn2(3) + hri1m * hj1p * xn2(4) &
94  + hri0p * hj0m * xn4(1) + hri1p * hj0m * xn4(2) &
95  + hri0p * hj1m * xn4(3) + hri1p * hj1m * xn4(4) &
96  + hri0p * hj0p * xn3(1) + hri1p * hj0p * xn3(2) &
97  + hri0p * hj1p * xn3(3) + hri1p * hj1p * xn3(4)
98 
99  xs = hi0m * hsj0m * xn1(1) + hi1m * hsj0m * xn1(2) &
100  + hi0m * hsj1m * xn1(3) + hi1m * hsj1m * xn1(4) &
101  + hi0m * hsj0p * xn2(1) + hi1m * hsj0p * xn2(2) &
102  + hi0m * hsj1p * xn2(3) + hi1m * hsj1p * xn2(4) &
103  + hi0p * hsj0m * xn4(1) + hi1p * hsj0m * xn4(2) &
104  + hi0p * hsj1m * xn4(3) + hi1p * hsj1m * xn4(4) &
105  + hi0p * hsj0p * xn3(1) + hi1p * hsj0p * xn3(2) &
106  + hi0p * hsj1p * xn3(3) + hi1p * hsj1p * xn3(4)
107 
108  if (type_interp == 1) return
109 
110  if (type_interp == 2) then
111 
112  hrri0m = 1.5_r8 * r
113  hrri1m = 1.5_r8 * r - 0.5_r8
114 
115  hssj0m = 1.5_r8 * s
116  hssj1m = 1.5_r8 * s - 0.5_r8
117 
118  hrri0p = -1.5_r8 * r
119  hrri1p = 1.5_r8 * r + 0.5_r8
120 
121  hssj0p = -1.5_r8 * s
122  hssj1p = 1.5_r8 * s + 0.5_r8
123 
124  xrr = hrri0m * hj0m * xn1(1) + hrri1m * hj0m * xn1(2) &
125  + hrri0m * hj1m * xn1(3) + hrri1m * hj1m * xn1(4) &
126  + hrri0m * hj0p * xn2(1) + hrri1m * hj0p * xn2(2) &
127  + hrri0m * hj1p * xn2(3) + hrri1m * hj1p * xn2(4) &
128  + hrri0p * hj0m * xn4(1) + hrri1p * hj0m * xn4(2) &
129  + hrri0p * hj1m * xn4(3) + hrri1p * hj1m * xn4(4) &
130  + hrri0p * hj0p * xn3(1) + hrri1p * hj0p * xn3(2) &
131  + hrri0p * hj1p * xn3(3) + hrri1p * hj1p * xn3(4)
132 
133  xss = hi0m * hssj0m * xn1(1) + hi1m * hssj0m * xn1(2) &
134  + hi0m * hssj1m * xn1(3) + hi1m * hssj1m * xn1(4) &
135  + hi0m * hssj0p * xn2(1) + hi1m * hssj0p * xn2(2) &
136  + hi0m * hssj1p * xn2(3) + hi1m * hssj1p * xn2(4) &
137  + hi0p * hssj0m * xn4(1) + hi1p * hssj0m * xn4(2) &
138  + hi0p * hssj1m * xn4(3) + hi1p * hssj1m * xn4(4) &
139  + hi0p * hssj0p * xn3(1) + hi1p * hssj0p * xn3(2) &
140  + hi0p * hssj1p * xn3(3) + hi1p * hssj1p * xn3(4)
141 
142  xrs = hri0m * hsj0m * xn1(1) + hri1m * hsj0m * xn1(2) &
143  + hri0m * hsj1m * xn1(3) + hri1m * hsj1m * xn1(4) &
144  + hri0m * hsj0p * xn2(1) + hri1m * hsj0p * xn2(2) &
145  + hri0m * hsj1p * xn2(3) + hri1m * hsj1p * xn2(4) &
146  + hri0p * hsj0m * xn4(1) + hri1p * hsj0m * xn4(2) &
147  + hri0p * hsj1m * xn4(3) + hri1p * hsj1m * xn4(4) &
148  + hri0p * hsj0p * xn3(1) + hri1p * hsj0p * xn3(2) &
149  + hri0p * hsj1p * xn3(3) + hri1p * hsj1p * xn3(4)
150 
151  else
152 
153  ps = hi0m * hj0m * pn1(1) + hi1m * hj0m * pn1(2) &
154  + hi0m * hj1m * pn1(3) + hi1m * hj1m * pn1(4) &
155  + hi0m * hj0p * pn2(1) + hi1m * hj0p * pn2(2) &
156  + hi0m * hj1p * pn2(3) + hi1m * hj1p * pn2(4) &
157  + hi0p * hj0m * pn4(1) + hi1p * hj0m * pn4(2) &
158  + hi0p * hj1m * pn4(3) + hi1p * hj1m * pn4(4) &
159  + hi0p * hj0p * pn3(1) + hi1p * hj0p * pn3(2) &
160  + hi0p * hj1p * pn3(3) + hi1p * hj1p * pn3(4)
161 
162  yr = hri0m * hj0m * yn1(1) + hri1m * hj0m * yn1(2) &
163  + hri0m * hj1m * yn1(3) + hri1m * hj1m * yn1(4) &
164  + hri0m * hj0p * yn2(1) + hri1m * hj0p * yn2(2) &
165  + hri0m * hj1p * yn2(3) + hri1m * hj1p * yn2(4) &
166  + hri0p * hj0m * yn4(1) + hri1p * hj0m * yn4(2) &
167  + hri0p * hj1m * yn4(3) + hri1p * hj1m * yn4(4) &
168  + hri0p * hj0p * yn3(1) + hri1p * hj0p * yn3(2) &
169  + hri0p * hj1p * yn3(3) + hri1p * hj1p * yn3(4)
170 
171  ys = hi0m * hsj0m * yn1(1) + hi1m * hsj0m * yn1(2) &
172  + hi0m * hsj1m * yn1(3) + hi1m * hsj1m * yn1(4) &
173  + hi0m * hsj0p * yn2(1) + hi1m * hsj0p * yn2(2) &
174  + hi0m * hsj1p * yn2(3) + hi1m * hsj1p * yn2(4) &
175  + hi0p * hsj0m * yn4(1) + hi1p * hsj0m * yn4(2) &
176  + hi0p * hsj1m * yn4(3) + hi1p * hsj1m * yn4(4) &
177  + hi0p * hsj0p * yn3(1) + hi1p * hsj0p * yn3(2) &
178  + hi0p * hsj1p * yn3(3) + hi1p * hsj1p * yn3(4)
179  end if
180 
181  return
182 
183  end subroutine interpolation
184 
185 !----------------------------------------------------------------------------
186  subroutine transfer_1d_profile(x_in, f_in, x_out, f_out, df_out, &
187  spline_type, monotonic)
188 !----------------------------------------------------------------------------
189 ! This subroutine transfers a 1D profile f_in given on x_in to the profile
190 ! f_out given on x_out by means of spline interpolation.
191 ! df_out holds the derivatives df/dx on output if specified.
192 ! for spline_type == 1 the first derivatives are extrapolated onto the
193 ! boundaries
194 !----------------------------------------------------------------------------
195 
196  use mod_profiles
197  use helena_spline
198 
199  real(r8), dimension(:) :: x_in, f_in
200  real(r8), dimension(:) :: x_out, f_out
201  real(r8), dimension(:), intent(inout), optional :: df_out
202  integer(itm_i4), optional :: spline_type
203  logical, intent(in), optional :: monotonic
204 
205  type(spline_coefficients) :: f_spline
206  real(r8), dimension(3) :: abltg
207  real(r8) :: df1 = 0._r8, dfn = 0._r8
208  real(r8) :: df2, df3
209  real(r8) :: dfn1, dfn2
210  integer(itm_i4) :: s_type
211  integer(itm_i4) :: n
212  integer(itm_i4) :: i
213  logical :: inverted
214 
215 !-- natural spline as default
216  if (.not. present(spline_type)) then
217  s_type = 2
218  else
219  s_type = spline_type
220  end if
221 
222  if (size(x_in) /= size(f_in) .or. size(x_out) /= size(f_out)) &
223  stop 'Fatal error in transfer_1d_profile: size mismatch!'
224 
225  if (present(df_out)) then
226  if (size(x_out) /= size(df_out)) &
227  stop 'Fatal error in transfer_1d_profile: size mismatch!'
228  end if
229 
230  inverted = .false.
231  if (x_in(size(x_in)) < x_in(1)) then
232  inverted = .true. ! inverted abscissa
233  x_in = -x_in
234  x_out = -x_out
235  end if
236 
237 !-- extrapolate first derivatives for s_type == 1
238  if (s_type == 1) then
239  n = size(f_in)
240  df2 = (f_in(3) - f_in(1)) / (x_in(3) - x_in(1))
241  df3 = (f_in(4) - f_in(2)) / (x_in(4) - x_in(2))
242  dfn1 = (f_in(n) - f_in(n - 2)) / (x_in(n) - x_in(n - 2))
243  dfn2 = (f_in(n - 1) - f_in(n - 3)) / (x_in(n - 1) - x_in(n - 3))
244 
245  df1 = (x_in(3) - x_in(1)) / (x_in(3) - x_in(2)) * df2 &
246  - (x_in(2) - x_in(1)) / (x_in(3) - x_in(2)) * df3
247  dfn = (x_in(n) - x_in(n - 2)) / (x_in(n - 1) - x_in(n - 2)) * dfn1 &
248  - (x_in(n) - x_in(n - 1)) / (x_in(n - 1) - x_in(n - 2)) * dfn2
249  if(present(monotonic)) then
250  write(*,*) 'DPC: dfN, monotonic = ', dfn, monotonic
251  if(dfn .lt. 0.0_r8) then
252  dfn = 0.0_r8
253  write(*,*) 'DPC: dfN changed to ', dfn
254  endif
255  else
256  write(*,*) 'DPC: dfN = ', dfn
257  endif
258  end if
259 
260  call allocate_spline_coefficients(f_spline, size(f_in))
261  call spline(size(x_in), x_in, f_in, df1, dfn, s_type, &
262  f_spline)
263 
264  do i = 1, size(x_out)
265  f_out(i) = spwert(size(x_in), x_out(i), f_spline, x_in, abltg, 1)
266  if (present(df_out)) df_out(i) = abltg(1)
267  end do
268 
269 !-- enforce monotonicity if monotonic == .true.
270  if (present(monotonic)) then
271  if (monotonic) then
272  do i = 2, size(x_out) - 1
273  if ((f_out(i) - f_out(i - 1)) * (f_out(i + 1) - f_out(i)) < 0._r8) &
274  then
275  write(*,*) 'ERR?: monotonicity fix applied to ', &
276  f_out(i - 1), f_out(i), f_out(i + 1)
277  f_out(i) = f_out(i - 1) + (x_out(i) - x_out(i - 1)) &
278  * (f_out(i + 1) - f_out(i - 1)) / (x_out(i + 1) - x_out(i - 1))
279  write(*,*) 'ERR?: resulting in ', &
280  f_out(i - 1), f_out(i), f_out(i + 1)
281  if (present(df_out)) &
282  df_out(i) = (f_out(i + 1) - f_out(i - 1)) / (x_out(i + 1) &
283  - x_out(i - 1))
284  end if
285  end do
286  end if
287  end if
288 
289  call deallocate_spline_coefficients(f_spline)
290 
291  if (inverted) then
292  x_in = -x_in
293  x_out = -x_out
294  if (present(df_out)) df_out = -df_out
295  end if
296 
297  end subroutine transfer_1d_profile
298 
299 end module mod_interpolation
subroutine interpolation(type_interp, xn1, xn2, xn3, xn4, r, s, x, xr, xs, xrs, xrr, xss, yn1, yn2, yn3, yn4, pn1, pn2, pn3, pn4, yr, ys, ps)
subroutine allocate_spline_coefficients(spline, n)
subroutine spline(N, X, Y, ALFA, BETA, TYP, A, B, C, D)
Definition: solution6.f90:655
REAL *8 function spwert(N, XWERT, A, B, C, D, X, ABLTG)
Definition: solution6.f90:155
subroutine deallocate_spline_coefficients(spline)
subroutine transfer_1d_profile(x_in, f_in, x_out, f_out, df_out, spline_type, monotonic)