inter_module.f90
Go to the documentation of this file.
1 !> @file inter_mod.f90
2 !!
3 !! The error file code for this file is ***W27***.
4 !! This file contains the module \ref inter_module
5 
6 !>
7 !! @brief Module \ref inter_module with interpolation routines
8 !!
9 !! This routines are used to interpolate the hydrodynamic
10 !! quantaties (e.g., temperature, density,..)
11 !!
12 #include "macros.h"
14  implicit none
15 
16  !
17  ! Public and private fields and methods of the module (everything is public)
18  !
19  public:: &
22  private:: &
25 
26 contains
27 
28 !>
29 !! Linear interpolation in lin-log space.
30 !!
31 !! This routine assumes that the x and y arrays are given
32 !! in the form of {x_i, log(y_i)}.
33 !! An optional argument flin allows to control the return value:
34 !! - if flin is absent: return exp(log(y)) = y;
35 !! - if flin is present: return log(y).
36 !!
37 !! \b Edited:
38 !! - 11.01.14
39 !! .
40 subroutine lininter(n,ref_array,ref_value,array,res,flin)
41  implicit none
42 
43  integer,intent(in) :: n !< array sizes
44  real(r_kind),dimension(n),intent(in) :: ref_array !< array of x-values {x_i}
45  real(r_kind),dimension(n),intent(in) :: array !< array of log(y)-values {log(y_i)}
46  real(r_kind),intent(in) :: ref_value !< value of log(x)
47  real(r_kind),intent(out) :: res !< interpolated value of y
48  logical,intent(in),optional :: flin !< if present, return log(y) instead of y
49  !
50  real(r_kind) :: grad
51  integer :: i,ii
52  logical :: linear
53 
54  ! Default value
55  if (.not. present(flin)) then
56  linear = .false.
57  else
58  linear = flin
59  end if
60 
61  ii = 1
62  do i = 1,n
63  if (ref_value .le. ref_array(i)) exit
64  ii = i+1
65  end do
66 
67  if (ii.eq.1) then
68  res = array(1)
69  else if (ii.gt.n) then
70  res = array(n)
71  else
72  grad = (ref_value-ref_array(ii-1))/(ref_array(ii)-ref_array(ii-1))
73  res = array(ii-1) + grad*(array(ii)-array(ii-1))
74  end if
75 
76  if(linear) then
77  return
78  else
79  res= dexp(res)
80  return
81  end if
82 
83 end subroutine lininter
84 
85 
86 
87 !> Interface for 1D interpolation routines.
88 !!
89 !! This routine is a wrapper for the 1D interpolation routines
90 !! lininter, cubinter, akimainter, makimainter, and pchipinter.
91 !! The interpolation type is controlled by the optional argument
92 !! itype. If itype is absent, \ref interp_mode is used.
93 !! The optional argument flin allows to control the return value:
94 !! - if flin is absent: return exp(log(y)) = y;
95 !! - if flin is present: return log(y).
96 !!
97 !! @author M. Reichert
98 !! @date 01.05.2023
99 subroutine interp1d(n,xp,xb,yp,res,flin,itype)
101  use parameter_class, only: interp_mode
102  integer,intent(in) :: n !< array sizes
103  real(r_kind),dimension(n),intent(in) :: xp !< array of x-values
104  real(r_kind),intent(in) :: xb !< value of x
105  real(r_kind),dimension(n),intent(in) :: yp !< array of log(y)-values
106  real(r_kind),intent(out) :: res !< interpolated value of y
107  logical,intent(in),optional :: flin !< if present, return log(y) instead of y
108  integer,intent(in),optional :: itype!< Type of interpolation (1: linear, 2: cubic)
109  ! Internal variables
110  integer :: interp_type
111  logical :: linear
112 
113  ! Set default values
114  if (.not. present(itype)) then
115  interp_type = interp_mode
116  else
117  interp_type = itype
118  end if
119 
120  if (.not. present(flin)) then
121  linear = .false.
122  else
123  linear = flin
124  end if
125 
126  ! Decide on desired interpolation type
127  if (interp_type .eq. itype_linear) then
128  call lininter(n,xp,xb,yp,res,linear)
129  else if (interp_type .eq. itype_cubic) then
130  call cubinter(n,xp,xb,yp,res,linear)
131  else if (interp_type .eq. itype_akima) then
132  call akimainter(n,xp,xb,yp,res,linear)
133  else if (interp_type .eq. itype_makima) then
134  call makimainter(n,xp,xb,yp,res,linear)
135  else if (interp_type .eq. itype_pchip) then
136  call pchipinter(n,xp,xb,yp,res,linear)
137  else
138  call raise_exception("Interpolation type not known. Got "//&
139  int_to_str(interp_type)//&
140  ". Try to change interp_mode to a valid value.",&
141  "interp1d",270004)
142  end if
143 
144 end subroutine interp1d
145 
146 
147 
148 !>
149 !! Cubic interpolation in log-log space. Here, it is assumed that
150 !!
151 !! the x and y arrays are given in the form of {x_i, log(y_i)},
152 !! but before interpolating the x coordinate, it is transformed
153 !! to a log space: {log(x_i), log(y_i)}.
154 !! An optional argument flin allows to control the return value:
155 !! - if flin is absent: return exp(log(y)) = y;
156 !! - if flin is present: return log(y).
157 !!
158 !! \b Edited:
159 !! - 14.01.14
160 !! .
161 subroutine cubinter (n,xp,xb,yp,res,flin)
162  implicit none
163 
164  integer,intent(in) :: n !< array sizes
165  real(r_kind),dimension(n),intent(in) :: xp !< array of x-values
166  real(r_kind),intent(in) :: xb !< value of x
167  real(r_kind),dimension(n),intent(in) :: yp !< array of log(y)-values
168  real(r_kind),intent(out) :: res !< interpolated value of y
169  logical,intent(in),optional :: flin !< if present, return log(y) instead of y
170  !
171  integer :: ii,k
172  real(r_kind) :: x,x1,x2,x3,x4,x12,x13,x14,x23,x24,x34
173  logical :: linear
174 
175  if(present(flin)) then
176  linear= flin
177  else
178  linear= .false.
179  end if
180 
181  x= xb
182  do ii= 1,n
183  if (xb .le. xp(ii)) exit
184  end do
185  if (x.le.xp(1)) then
186  res= yp(1)
187  else if (x.ge.xp(n)) then
188  res= yp(n)
189  else if(ii.le.2) then ! linear interpolation in lin-log space
190  x1= x - xp(1)
191  x2= x - xp(2)
192  x12= x2-x1
193  res= (yp(1)*x2 - yp(2)*x1)/x12
194  else if(ii.eq.n) then ! linear interpolation in log-log space
195  x1= log(x/xp(n-1))
196  x2= log(x/xp(n))
197  x12= x2-x1
198  res= (yp(n-1)*x2 - yp(n)*x1)/x12
199  else ! cubic interpolation in log-log space
200  k= min(max(ii-2,2),n-3)
201  x= log(x)
202  x1= x - log(xp(k))
203  x2= x - log(xp(k+1))
204  x3= x - log(xp(k+2))
205  x4= x - log(xp(k+3))
206 
207  x12= x2-x1
208  x13= x3-x1
209  x14= x4-x1
210  x23= x3-x2
211  x24= x4-x2
212  x34= x4-x3
213 
214  res= yp(k) *x2*x3*x4/(x12*x13*x14) &
215  - yp(k+1)*x1*x3*x4/(x12*x23*x24) &
216  + yp(k+2)*x1*x2*x4/(x13*x23*x34) &
217  - yp(k+3)*x1*x2*x3/(x14*x24*x34)
218  endif
219 
220  if(linear) then
221  return
222  else
223  res= dexp(res)
224  return
225  end if
226 end subroutine cubinter
227 
228 
229 !> PCHIP interpolation in lin-log space.
230 !!
231 !! The Piecewise Cubic Hermite Interpolating Polynomial (PCHIP)
232 !! interpolation is a method for interpolating data points where
233 !! every section between points is monoton. The interpolation
234 !! avoids overshoots and undershoots and is close to the linear
235 !! interpolation, but having the first derivative continuous.
236 !!
237 !! @see F. N. Fritsch and R. E. Carlson, Monotone Piecewise Cubic
238 !! Interpolation, SIAM Journal on Numerical Analysis, 17(2),
239 !! 1980, pp. 238-246.
240 !! [Steffen 1990](https://ui.adsabs.harvard.edu/abs/1990A%26A...239..443S/abstract)
241 !! @author: M. Reichert
242 !! @date: 01.05.2023
243 subroutine pchipinter(n,xp,xb,yp,res,flin)
244  implicit none
245  integer,intent(in) :: n !< array sizes
246  real(r_kind),dimension(n),intent(in) :: xp !< array of x-values
247  real(r_kind),intent(in) :: xb !< value of x
248  real(r_kind),dimension(n),intent(in) :: yp !< array of log(y)-values
249  real(r_kind),intent(out) :: res !< interpolated value of y
250  logical,intent(in),optional :: flin !< if present, return log(y) instead of y
251  ! Internal variables
252  integer :: ii, i
253  real(r_kind) :: a, b, c, d
254  real(r_kind) :: hi, him1, hip1
255  real(r_kind) :: si, sim1, sip1
256  real(r_kind) :: pi, pip1
257  real(r_kind) :: yi_prime, yip1_prime
258  real(r_kind) :: x1, x2
259  real(r_kind) :: delt
260  logical :: linear
261 
262  if(present(flin)) then
263  linear= flin
264  else
265  linear= .false.
266  end if
267 
268  ! Find the index for the interpolation interval
269  do ii= 1,n
270  if (xb .le. xp(ii)) exit
271  end do
272  ii = ii-1
273 
274  ! Extrapolation, value is smaller than grid
275  if (xb.le.xp(1)) then
276  res= yp(1)
277  ! Extrapolation, value is larger than grid
278  else if (xb.ge.xp(n)) then
279  res= yp(n)
280  ! Value is at left border
281  else if(ii.lt.2) then
282  ! Interpolate linear
283  x1= xb - xp(ii)
284  x2= xb - xp(ii+1)
285  res= (yp(ii)*x2 - yp(ii+1)*x1)/(x2-x1)
286  ! Value is at left border
287  else if(ii.gt.n-2) then
288  ! Interpolate linear
289  x1= xb - xp(ii)
290  x2= xb - xp(ii+1)
291  res= (yp(ii)*x2 - yp(ii+1)*x1)/(x2-x1)
292  else
293  ! Normal case, use pchip interpolation
294  ! Values in interval
295  hi = xp(ii+1)-xp(ii)
296  si = (yp(ii+1)-yp(ii))/hi
297  ! Values to the left
298  him1 = xp(ii)-xp(ii-1)
299  sim1 = (yp(ii)-yp(ii-1))/him1
300  ! Values to the right
301  hip1 = xp(ii+2)-xp(ii+1)
302  sip1 = (yp(ii+2)-yp(ii+1))/hip1
303 
304  pi = (hi*sim1+him1*si)/(hi+him1)
305  pip1 = (hip1*si+hi*sip1)/(hip1+hi)
306 
307  ! Restrict slopes to ensure monotonicity
308  if (si*sim1 .le. 0) then
309  yi_prime = 0
310  elseif ((dabs(pi)>2*dabs(sim1)) .or. (dabs(pi)>2*dabs(si))) then
311  yi_prime = 2*sign(1.d0,si)*min(dabs(sim1),dabs(si))
312  else
313  yi_prime=pi
314  end if
315 
316  if (sip1*si .le. 0) then
317  yip1_prime = 0
318  elseif ((dabs(pip1)>2*dabs(si)) .or. (dabs(pip1)>2*dabs(sip1))) then
319  yip1_prime = 2*sign(1.d0,si)*min(dabs(sip1),dabs(si))
320  else
321  yip1_prime=pip1
322  end if
323 
324  a = (yi_prime+yip1_prime-2*si)/hi**2
325  b = (3*si-2*yi_prime-yip1_prime)/hi
326  c = yi_prime
327  d = yp(ii)
328 
329  delt = xb-xp(ii)
330  ! Calculate interpolated value
331  res = a*delt**3 + b*delt**2 + c*delt + d
332 
333  end if
334 
335  if(linear) then
336  return
337  else
338  res= dexp(res)
339  return
340  end if
341 
342 end subroutine pchipinter
343 
344 
345 
346 !> Interpolation using prescription of Akima
347 !!
348 !! The interpolation is a spline interpolation that tries
349 !! to avoid overshoots.
350 !!
351 !! Here, it is assumed that
352 !! the x and y arrays are given in the form of {x_i, log(y_i)},
353 !! but before interpolating the x coordinate, it is transformed
354 !! to a log space: {log(x_i), log(y_i)}.
355 !! An optional argument flin allows to control the return value:
356 !! - if flin is absent: return exp(log(y)) = y;
357 !! - if flin is present: return log(y).
358 !! .
359 !!
360 !! @see [Akima, Journal of the ACM, 17: 589–602, 1970](https://web.archive.org/web/20201218210437/http://www.leg.ufpr.br/lib/exe/fetch.php/wiki:internas:biblioteca:akima.pdf),
361 !! [Wikipedia: Akima Spline](https://en.wikipedia.org/wiki/Akima_spline)
362 !! @author M. Reichert
363 !! @date 30.04.2023
364 subroutine akimainter(n,xp,xb,yp,res,flin)
365  implicit none
366  integer,intent(in) :: n !< array sizes
367  real(r_kind),dimension(n),intent(in) :: xp !< array of x-values
368  real(r_kind),intent(in) :: xb !< value of x
369  real(r_kind),dimension(n),intent(in) :: yp !< array of log(y)-values
370  real(r_kind),intent(out) :: res !< interpolated value of y
371  logical,intent(in),optional :: flin !< if present, return log(y) instead of y
372  ! Internal variables
373  real(r_kind) :: xval(6), yval(6), mval(5), sval(2)
374  integer :: ii, i
375  real(r_kind) :: a, b, c, d
376  real(r_kind) :: x1,x2
377  real(r_kind) :: denom
378  logical :: linear
379 
380  if(present(flin)) then
381  linear= flin
382  else
383  linear= .false.
384  end if
385 
386  xval = 0.0d0
387  yval = 0.0d0
388  mval = 0.0d0
389  sval = 0.0d0
390 
391 
392  ! Find the index for the interpolation interval
393  do ii= 1,n
394  if (xb .le. xp(ii)) exit
395  end do
396  ii = ii-1
397 
398  ! Extrapolation, value is smaller than grid
399  if (xb.le.xp(1)) then
400  res= yp(1)
401  ! Extrapolation, value is larger than grid
402  else if (xb.ge.xp(n)) then
403  res= yp(n)
404  ! Value is at left border
405  else if(ii.lt.3) then
406  ! Interpolate linear
407  x1= xb - xp(ii)
408  x2= xb - xp(ii+1)
409  res= (yp(ii)*x2 - yp(ii+1)*x1)/(x2-x1)
410  ! Value is at left border
411  else if(ii.gt.n-3) then
412  ! Interpolate linear
413  x1= xb - xp(ii)
414  x2= xb - xp(ii+1)
415  res= (yp(ii)*x2 - yp(ii+1)*x1)/(x2-x1)
416  else
417  ! Normal case, use Akima interpolation
418 
419  ! Save the required values of the grid for the interpolation
420  xval(1:6) = xp(ii-2:ii+3)
421  yval(1:6) = yp(ii-2:ii+3)
422  ! Calculate the derivative
423  mval(1:5) = (yval(2:6) - yval(1:5)) / (xval(2:6) - xval(1:5))
424 
425  ! Get si and si+1
426  i = 3
427  sval(1) = ((dabs(mval(i+1)-mval(i))*mval(i-1) + dabs(mval(i-1)-mval(i-2))*mval(i)))
428  denom = (dabs(mval(i+1)-mval(i)) + dabs(mval(i-1)-mval(i-2)))
429  ! Avoid division by something very small
430  if (denom .gt. 1e-8) then
431  sval(1) = sval(1)/denom
432  else
433  sval(1) = (mval(i-1)+mval(i))/2d0
434  end if
435  sval(2) = ((dabs(mval(i+2)-mval(i+1))*mval(i) + dabs(mval(i)-mval(i-1))*mval(i+1)))
436  denom = (dabs(mval(i+2)-mval(i+1)) + dabs(mval(i)-mval(i-1)))
437  if (denom .gt. 1e-8) then
438  sval(2) = sval(2)/denom
439  else
440  sval(2) = (mval(i)+mval(i+1))/2d0
441  end if
442  ! Get the coefficients
443  a = yval(i)
444  b = sval(1)
445  c = (3.0d0 * mval(i) - 2.0d0 * sval(1) - sval(2)) / (xval(i+1) - xval(i))
446  d = (sval(1) + sval(2) - 2.0d0 * mval(i)) / (xval(i+1) - xval(i))**2
447  ! Calculate the results
448  res = a + b * (xb - xval(i)) + c * (xb - xval(i))**2 + d * (xb - xval(i))**3
449  end if
450 
451  if(linear) then
452  return
453  else
454  res= dexp(res)
455  return
456  end if
457 
458 end subroutine akimainter
459 
460 
461 
462 !> Interpolation using modified prescription of Akima
463 !!
464 !! The interpolation is a spline interpolation that tries
465 !! to avoid overshoots. It is doing this slightly more
466 !! radically than the Akima interpolation, but not as
467 !! strong as the pchip interpolation.
468 !!
469 !! Here, it is assumed that
470 !! the x and y arrays are given in the form of {x_i, log(y_i)},
471 !! but before interpolating the x coordinate, it is transformed
472 !! to a log space: {log(x_i), log(y_i)}.
473 !! An optional argument flin allows to control the return value:
474 !! - if flin is absent: return exp(log(y)) = y;
475 !! - if flin is present: return log(y).
476 !! .
477 !!
478 !! @see https://blogs.mathworks.com/cleve/2019/04/29/makima-piecewise-cubic-interpolation/
479 !! @author M. Reichert
480 !! @date 30.04.2023
481 subroutine makimainter(n,xp,xb,yp,res,flin)
482  implicit none
483  integer,intent(in) :: n !< array sizes
484  real(r_kind),dimension(n),intent(in) :: xp !< array of x-values
485  real(r_kind),intent(in) :: xb !< value of x
486  real(r_kind),dimension(n),intent(in) :: yp !< array of log(y)-values
487  real(r_kind),intent(out) :: res !< interpolated value of y
488  logical,intent(in),optional :: flin !< if present, return log(y) instead of y
489  ! Internal variables
490  real(r_kind) :: xval(6), yval(6), mval(5), sval(2)
491  integer :: ii, i
492  real(r_kind) :: a, b, c, d
493  real(r_kind) :: x1,x2
494  real(r_kind) :: denom
495  logical :: linear
496 
497  if(present(flin)) then
498  linear= flin
499  else
500  linear= .false.
501  end if
502 
503  xval = 0.0d0
504  yval = 0.0d0
505  mval = 0.0d0
506  sval = 0.0d0
507 
508 
509  ! Find the index for the interpolation interval
510  do ii= 1,n
511  if (xb .le. xp(ii)) exit
512  end do
513  ii = ii-1
514 
515  ! Extrapolation, value is smaller than grid
516  if (xb.le.xp(1)) then
517  res= yp(1)
518  ! Extrapolation, value is larger than grid
519  else if (xb.ge.xp(n)) then
520  res= yp(n)
521  ! Value is at left border
522  else if(ii.lt.3) then
523  ! Interpolate linear
524  x1= xb - xp(ii)
525  x2= xb - xp(ii+1)
526  res= (yp(ii)*x2 - yp(ii+1)*x1)/(x2-x1)
527  ! Value is at left border
528  else if(ii.gt.n-3) then
529  ! Interpolate linear
530  x1= xb - xp(ii)
531  x2= xb - xp(ii+1)
532  res= (yp(ii)*x2 - yp(ii+1)*x1)/(x2-x1)
533  else
534  ! Normal case, use Akima interpolation
535 
536  ! Save the required values of the grid for the interpolation
537  xval(1:6) = xp(ii-2:ii+3)
538  yval(1:6) = yp(ii-2:ii+3)
539  ! Calculate the derivative
540  mval(1:5) = (yval(2:6) - yval(1:5)) / (xval(2:6) - xval(1:5))
541 
542  ! Get si and si+1
543  i = 3
544  sval(1) = ((dabs(mval(i+1)-mval(i)) + dabs(mval(i+1)+mval(i))/2d0)*mval(i-1) + &
545  (dabs(mval(i-1)-mval(i-2)) + dabs(mval(i-1)+mval(i-2))/2d0)*mval(i))
546 
547  denom = ((dabs(mval(i+1)-mval(i)) + dabs(mval(i+1)+mval(i))/2d0) + &
548  (dabs(mval(i-1)-mval(i-2)) + dabs(mval(i-1)+mval(i-2))/2d0))
549  ! Avoid division by something very small
550  if (denom .gt. 1e-8) then
551  sval(1) = sval(1)/denom
552  else
553  sval(1) = (mval(i-1)+mval(i))/2d0
554  end if
555  sval(2) = (((dabs(mval(i+2)-mval(i+1)) + dabs(mval(i+2)+mval(i+1))/2d0)*mval(i) + &
556  (dabs(mval(i)-mval(i-1)) + dabs(mval(i)+mval(i-1))/2d0) *mval(i+1)))
557  denom = ((dabs(mval(i+2)-mval(i+1)) + dabs(mval(i+2)+mval(i+1))/2d0) + &
558  (dabs(mval(i)-mval(i-1)) + dabs(mval(i)+mval(i-1))/2d0))
559  if (denom .gt. 1e-8) then
560  sval(2) = sval(2)/denom
561  else
562  sval(2) = (mval(i)+mval(i+1))/2d0
563  end if
564  ! Get the coefficients
565  a = yval(i)
566  b = sval(1)
567  c = (3.0d0 * mval(i) - 2.0d0 * sval(1) - sval(2)) / (xval(i+1) - xval(i))
568  d = (sval(1) + sval(2) - 2.0d0 * mval(i)) / (xval(i+1) - xval(i))**2
569  ! Calculate the results
570  res = a + b * (xb - xval(i)) + c * (xb - xval(i))**2 + d * (xb - xval(i))**3
571  end if
572 
573  if(linear) then
574  return
575  else
576  res= dexp(res)
577  return
578  end if
579 
580 end subroutine makimainter
581 
582 
583 !> Get indices of the grid for given x- and y- values
584 !!
585 !! @author: M. Reichert
586 !! @date: 06.07.22
587 subroutine get_indice_2d(xval,yval,x,y,x_dim,y_dim,indices)
588  implicit none
589  integer,intent(in) :: x_dim, y_dim !< Dimension of x- and y-
590  real(r_kind),intent(in) :: xval,yval !< Function values
591  real(r_kind),dimension(x_dim),intent(in) :: x !< X-grid values
592  real(r_kind),dimension(y_dim),intent(in) :: y !< Y-grid values
593  integer,dimension(2,2),intent(out) :: indices !< Index in the grid
594  ! Internal variables
595  integer :: i !< Loop variables
596 
597  ! Index in x-direction
598  do i=2,x_dim-1
599  if (xval .lt. x(i)) exit
600  end do
601  indices(1,1)=i-1
602  indices(1,2)=i
603 
604  ! Index in y-direction
605  do i=2,y_dim-1
606  if (yval .lt. y(i)) exit
607  end do
608  indices(2,1)=i-1
609  indices(2,2)=i
610 
611 end subroutine get_indice_2d
612 
613 
614 !> Calculate derivatives at all points in a given grid.
615 !!
616 !! These derivatives are necessary for the cubic interpolation.
617 !! The subroutine returns the derivative df/dx, df/dy, and ddf/dxdy.
618 !! They are second order accurate, i.e.,
619 !! \f[ df/dx = \frac{h_1^2 f(x+h_2) + (h_2^2-h_1^2)f(x)-h_2^2 f(x-h_1) }{h_1 h_2 (h_1+h_2)} \f]
620 !!
621 !! @author: M. Reichert
622 !! @date 06.07.22
623 subroutine calc_derivative_2d(f,x,y,dfx,dfy,dfxy,x_dim,y_dim)
624  implicit none
625  integer,intent(in) :: x_dim, y_dim !< Dimension of x- and y-
626  real(r_kind),dimension(x_dim, y_dim),intent(in) :: f !< Function values
627  real(r_kind),dimension(x_dim),intent(in) :: x !< x values
628  real(r_kind),dimension(y_dim),intent(in) :: y !< y values
629  real(r_kind),dimension(x_dim,y_dim),intent(inout) :: dfx !< Derivative with respect to x
630  real(r_kind),dimension(x_dim,y_dim),intent(inout) :: dfy !< Derivative with respect to y
631  real(r_kind),dimension(x_dim,y_dim),intent(inout) :: dfxy !< Derivative with respect to x and y
632  ! Internal variables
633  integer :: i, j !< Loop variables
634  real(r_kind) :: h1,h2 !< steps
635 
636  ! Calculate derivatives for every point
637  do i=1,x_dim
638  do j=1,y_dim
639  ! X-direction
640  if ((i .gt. 1) .and. (i .lt. x_dim) ) then
641  h1 = abs(x(i) -x(i-1))
642  h2 = abs(x(i+1)-x(i))
643  dfx(i,j) = h1**2*f(i+1,j)+(h2**2-h1**2)*f(i,j)-h2**2*f(i-1,j)
644  dfx(i,j) = dfx(i,j) / (h1*h2*(h1+h2))
645  elseif (i .eq. 1) then
646  h2 = abs(x(i+1)-x(i))
647  dfx(i,j) = (f(i+1,j)-f(i,j)) / (h2)
648  elseif (i .eq. x_dim) then
649  h1 = abs(x(i)-x(i-1))
650  dfx(i,j) = (f(i,j)-f(i-1,j)) / (h1)
651  end if
652 
653  ! Y-direction
654  if ((j .gt.1) .and. (j .lt. y_dim)) then
655  h1 = abs(y(j) -y(j-1))
656  h2 = abs(y(j+1)-y(j))
657  dfy(i,j) = h1**2*f(i,j+1)+(h2**2-h1**2)*f(i,j)-h2**2*f(i,j-1)
658  dfy(i,j) = dfy(i,j) / (h1*h2*(h1+h2))
659  elseif (j .eq. 1) then
660  h2 = abs(y(j+1)-y(j))
661  dfy(i,j) = (f(i,j+1)-f(i,j)) / (h2)
662  elseif (j .eq. y_dim) then
663  h1 = abs(y(j)-y(j-1))
664  dfy(i,j) = (f(i,j)-f(i,j-1)) / (h1)
665  end if
666  end do
667  end do
668 
669  ! Mixed partial derivatives
670  do i=1, x_dim
671  do j=1, y_dim
672  if ((j .gt. 1) .and. (j .lt. y_dim) ) then
673  h1 = abs(y(j) -y(j-1))
674  h2 = abs(y(j+1)-y(j))
675  dfxy(i,j) = h1**2*dfx(i,j+1)+(h2**2-h1**2)*dfx(i,j)-h2**2*dfx(i,j-1)
676  dfxy(i,j) = dfxy(i,j) / (h1*h2*(h1+h2))
677  elseif (j .eq. 1) then
678  h2 = abs(y(j+1)-y(j))
679  dfxy(i,j) = (dfx(i,j+1)-dfx(i,j)) / (h2)
680  elseif (j .eq. y_dim) then
681  h1 = abs(y(j)-y(j-1))
682  dfxy(i,j) = (dfx(i,j)-dfx(i,j-1)) / (h1)
683  end if
684  end do
685  end do
686 
687 end subroutine calc_derivative_2d
688 
689 
690 !> Interpolate linearly on 2 Dimensional grid
691 !!
692 !! Bilinear interpolation
693 !!
694 !! @see weak_inter
695 !!
696 !! @author: M. Reichert
697 !! @date: 06.07.22
698 !! .
699 function lininter_2d(xin,yin,x,y,f,x_dim,y_dim,indice,extrapolation) result (wr)
701  implicit none
702  integer,intent(in) :: x_dim, y_dim !< Dimension of x- and y-
703  real(r_kind),intent(in) :: xin,yin !< Function input values
704  real(r_kind),dimension(x_dim),intent(in) :: x !< X values
705  real(r_kind),dimension(y_dim),intent(in) :: y !< Y values
706  real(r_kind),dimension(x_dim,y_dim),intent(in) :: f !< Function and derivatives
707  integer,optional,intent(in) :: extrapolation !< 1: None; 2: constant
708  integer,dimension(2,2),optional,intent(in) :: indice !< Index where to interpolate
709  real(r_kind) :: wr !< Interpolated value (output)
710  ! Internal Variables
711  integer,dimension(2,2) :: ind !< Index where to interpolate
712  real(r_kind) :: xval,yval !< Internal function input values
713  real(r_kind) :: x1, x2, y1, y2 !< Corner values of the grid
714  integer :: extr !< Internal extr. flag
715  real(r_kind),dimension(2,2) :: weights !< Weights for interpolation
716 
717  ! Store variables in internal variable in order to be able to change them
718  xval=xin; yval=yin
719 
720  ! Get the index
721  if (.not. present(indice)) then
722  call get_indice_2d(xval,yval,x,y,x_dim,y_dim,ind)
723  else
724  ind(:,:) = indice(:,:)
725  end if
726 
727  ! Check that an extrapolation value is present
728  if (.not. present(extrapolation)) extr=1
729  if (present(extrapolation)) extr=extrapolation
730 
731  ! Check if extrapolation is necessary
732  if ((xval .lt. x(1)) .or. (yval .lt. y(1))) then
733  select case(extr)
734  case (1)
735  call raise_exception("Value for interpolation was out of bounds.",&
736  "inter_module",270003)
737  case (2)
738  xval= max(x(1),xval)
739  yval= max(y(1),yval)
740  case default
741  call raise_exception("Unknown interpolation type.",&
742  "inter_module",270004)
743  end select
744  elseif ((xval .gt. x(x_dim)) .or. (yval .gt. y(y_dim))) then
745  select case(extr)
746  case (1)
747  call raise_exception("Value for interpolation was out of bounds.",&
748  "inter_module",270003)
749  case (2)
750  xval= min(x(x_dim),xval)
751  yval= min(y(y_dim),yval)
752  case default
753  call raise_exception("Unknown interpolation type.",&
754  "inter_module",270004)
755  end select
756  end if
757 
758  ! Define x and y border points
759  x1 = x(ind(1,1))
760  x2 = x(ind(1,2))
761  y1 = y(ind(2,1))
762  y2 = y(ind(2,2))
763 
764  ! Weights for linear interpolation
765  weights(1,1) = ((x2-xval)*(y2-yval))/((x2-x1)*(y2-y1))
766  weights(1,2) = ((x2-xval)*(yval-y1))/((x2-x1)*(y2-y1))
767  weights(2,1) = ((xval-x1)*(y2-yval))/((x2-x1)*(y2-y1))
768  weights(2,2) = ((xval-x1)*(yval-y1))/((x2-x1)*(y2-y1))
769 
770  ! Get the interpolated value
771  wr = weights(1,1)*f(ind(1,1),ind(2,1)) + &
772  weights(1,2)*f(ind(1,1),ind(2,2)) + &
773  weights(2,1)*f(ind(1,2),ind(2,1)) + &
774  weights(2,2)*f(ind(1,2),ind(2,2))
775 
776  return
777 
778 end function lininter_2d
779 
780 
781 
782 
783 !> Cubic interpolate on 2-Dimensional grid
784 !!
785 !! This interpolation is a bicubic interpolation. For values outside the grid,
786 !! either a constant extrapolation is performed or an error is raised.
787 !!
788 !! @see weak_inter_bilinear, weak_inter, readweak_logft
789 !!
790 !! @author: Moritz Reichert
791 !! @date: 14.03.22
792 !!
793 !! @see [Bicubic interpolation](https://en.wikipedia.org/wiki/Bicubic_interpolation)
794 !! .
795 function cubinter_2d(xin,yin,x,y,f,dfx,dfy,dfxy,x_dim,y_dim,indice,extrapolation) result (wr)
797  implicit none
798  integer,intent(in) :: x_dim, y_dim !< Dimension of x- and y-
799  real(r_kind),intent(in) :: xin,yin !< Function input values
800  real(r_kind),dimension(x_dim),intent(in) :: x !< X values
801  real(r_kind),dimension(y_dim),intent(in) :: y !< Y values
802  real(r_kind),dimension(x_dim,y_dim),intent(in) :: f,dfx,dfy,dfxy !< Function and derivatives
803  integer,optional,intent(in) :: extrapolation !< 1: None; 2: constant
804  integer,dimension(2,2),optional,intent(in) :: indice !< Index where to interpolate
805  real(r_kind) :: wr !< Interpolated value (output)
806  ! Internal Variables
807  real(r_kind) :: xval,yval !< Internal function input values
808  real(r_kind),dimension(16,16) :: a_inv !< Inverse matrix to solve eq.
809  real(r_kind),dimension(16) :: vec,alphas !< Vectors for lin. eq.
810  integer,dimension(2,2) :: ind !< Index where to interpolate
811  real(r_kind),dimension(4,4) :: alphas_r !< Reshaped alpha coefficients
812  real(r_kind) :: x1, x2, y1, y2 !< Corner values of the grid
813  real(r_kind) :: xbar,ybar !< Helper variables
814  integer :: i,j !< Loop variable
815  integer :: extr !< Internal value for extr. flag
816 
817  ! Store variables in internal variable in order to be able to change them
818  xval=xin; yval=yin
819 
820  ! Get the index
821  if (.not. present(indice)) then
822  call get_indice_2d(xval,yval,x,y,x_dim,y_dim,ind)
823  else
824  ind(:,:) = indice(:,:)
825  end if
826 
827  ! Check that an extrapolation value is present
828  if (.not. present(extrapolation)) extr=2
829  if (present(extrapolation)) extr=extrapolation
830 
831  ! Check if extrapolation is necessary
832  if ((xval .lt. x(1)) .or. (yval .lt. y(1))) then
833  select case(extr)
834  case (1)
835  call raise_exception("Value for interpolation was out of bounds.",&
836  "inter_module",270003)
837  case (2)
838  xval= max(x(1),xval)
839  yval= max(y(1),yval)
840  case default
841  call raise_exception("Unknown interpolation type.",&
842  "inter_module",270004)
843  end select
844  elseif ((xval .gt. x(x_dim)) .or. (yval .gt. y(y_dim))) then
845  select case(extr)
846  case (1)
847  call raise_exception("Value for interpolation was out of bounds.",&
848  "inter_module",270003)
849  case (2)
850  xval= min(x(x_dim),xval)
851  yval= min(y(y_dim),yval)
852  case default
853  call raise_exception("Unknown interpolation type.",&
854  "inter_module",270004)
855  end select
856  end if
857 
858  ! Define x and y border points
859  x1 = x(ind(1,1))
860  x2 = x(ind(1,2))
861  y1 = y(ind(2,1))
862  y2 = y(ind(2,2))
863 
864  ! Define xbar and ybar
865  xbar = (xval-x1)/(x2-x1)
866  ybar = (yval-y1)/(y2-y1)
867 
868  ! Define helper inverse matrix to solve equation for determining
869  ! alpha coefficients later
870  a_inv = reshape( (/ 1, 0,-3, 2, 0, 0, 0, 0,-3, 0, 9,-6, 2, 0,-6, 4, &
871  0, 0, 3,-2, 0, 0, 0, 0, 0, 0,-9, 6, 0, 0, 6,-4, &
872  0, 0, 0, 0, 0, 0, 0, 0, 3, 0,-9, 6,-2, 0, 6,-4, &
873  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,-6, 0, 0,-6, 4, &
874  0, 1,-2, 1, 0, 0, 0, 0, 0,-3, 6,-3, 0, 2,-4, 2, &
875  0, 0,-1, 1, 0, 0, 0, 0, 0, 0, 3,-3, 0, 0,-2, 2, &
876  0, 0, 0, 0, 0, 0, 0, 0, 0, 3,-6, 3, 0,-2, 4,-2, &
877  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 3, 0, 0, 2,-2, &
878  0, 0, 0, 0, 1, 0,-3, 2,-2, 0, 6,-4, 1, 0,-3, 2, &
879  0, 0, 0, 0, 0, 0, 3,-2, 0, 0,-6, 4, 0, 0, 3,-2, &
880  0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 3,-2, 1, 0,-3, 2, &
881  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,-3, 2, 0, 0, 3,-2, &
882  0, 0, 0, 0, 0, 1,-2, 1, 0,-2, 4,-2, 0, 1,-2, 1, &
883  0, 0, 0, 0, 0, 0,-1, 1, 0, 0, 2,-2, 0, 0,-1, 1, &
884  0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 2,-1, 0, 1,-2, 1, &
885  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,-1, 0, 0,-1, 1 &
886  /), (/16, 16/) ) !< Helper Matrix
887 
888  ! Values for cubic interpolation
889  vec = (/f(ind(1,1),ind(2,1)),f(ind(1,2),ind(2,1)),f(ind(1,1),ind(2,2)),f(ind(1,2),ind(2,2)),&
890  (x2-x1)*dfx(ind(1,1),ind(2,1)),(x2-x1)*dfx(ind(1,2),ind(2,1)),(x2-x1)*dfx(ind(1,1),ind(2,2)),(x2-x1)*dfx(ind(1,2),ind(2,2)),&
891  (y2-y1)*dfy(ind(1,1),ind(2,1)),(y2-y1)*dfy(ind(1,2),ind(2,1)),(y2-y1)*dfy(ind(1,1),ind(2,2)),(y2-y1)*dfy(ind(1,2),ind(2,2)),&
892  (x2-x1)*(y2-y1)*dfxy(ind(1,1),ind(2,1)),(x2-x1)*(y2-y1)*dfxy(ind(1,2),ind(2,1)),&
893  (x2-x1)*(y2-y1)*dfxy(ind(1,1),ind(2,2)),(x2-x1)*(y2-y1)*dfxy(ind(1,2),ind(2,2))/)
894 
895  ! Solve lin. equation to get alpha coefficients
896  alphas = matmul(a_inv,vec)
897  ! Reshape to 4 x 4
898  alphas_r = reshape(alphas, (/4,4/))
899 
900  ! Calculate the interpolation result
901  wr = 0
902  do i=1,4
903  do j=1,4
904  wr = wr + alphas_r(i,j)*xbar**(i-1)*ybar**(j-1)
905  end do
906  end do
907 
908 end function cubinter_2d
909 
910 
911 
912 
913 
914 !>
915 !! The inverse of the 1D interpolation function.
916 !!
917 !! Interface to the inverse interpolation functions using either
918 !! Newton-Raphson or Brent's method.
919 !!
920 !! @author M. Reichert
921 !! @date 16.10.2024
922 !!
923 !! @see timestep_module::restrict_timestep
924 !!
925 subroutine inverse_interp1d (n,xp,xb,yp,res,flin,itype,reverse_type)
926  use parameter_class, only: interp_mode
928  implicit none
929  integer,intent(in) :: n !< array sizes
930  real(r_kind),dimension(n),intent(in) :: xp !< array of log(x)-values
931  real(r_kind),intent(in) :: xb !< value of x
932  real(r_kind),dimension(n),intent(in) :: yp !< array of y-values
933  real(r_kind),intent(inout) :: res !< interpolated value of y
934  logical,intent(in),optional :: flin !< flag for linear interpolation
935  integer,intent(in),optional :: itype !< interpolation type
936  integer, intent(in),optional :: reverse_type !< flag for reverse interpolation (1: NR, 2: Brent)
937 
938  ! Internal variables
939  logical :: linear
940  integer :: interp_type
941  integer :: rtype
942 
943  ! Set default values
944  ! Default: Interpolation type as given by parameters
945  if (.not. present(itype)) then
946  interp_type = interp_mode
947  else
948  interp_type = itype
949  end if
950 
951  ! Default: non-linear interpolation
952  if (.not. present(flin)) then
953  linear = .false.
954  else
955  linear = flin
956  end if
957 
958  ! Default: Newton-Raphson method
959  if (.not. present(reverse_type)) then
960  rtype = 1
961  else
962  rtype = reverse_type
963  end if
964 
965  ! Call the reverse interpolation
966  if (rtype .eq. 1) then
967  call inverse_nr(n,xp,xb,yp,res,linear,interp_type)
968  else if (rtype .eq. 2) then
969  call inverse_brent(n,xp,xb,yp,res,linear,interp_type)
970  else
971  call raise_exception("Unknown reverse interpolation method.",&
972  "inverse_interp1d", 270004)
973  end if
974 
975 
976  return
977 end subroutine inverse_interp1d
978 
979 
980 
981 !>
982 !! The inverse of the 1D interpolation function.
983 !!
984 !! Finds the inverse of interp1d and returns the value of x.
985 !! This is done by using a Newton-Raphson method.
986 !!
987 !! @note The result depends on xb, because x_i does not necessarily have
988 !! to be monotonic. The result should be the closest value to xb.
989 !! This is however not always the case in which brents method might be
990 !! more suitable.
991 !!
992 !! @author M. Reichert
993 !!
994 !! \b Edited:
995 !! - 30.01.23
996 !! .
997 subroutine inverse_nr (n,xp,xb,yp,res,flin,itype)
998  implicit none
999 
1000  integer,intent(in) :: n !< array sizes
1001  real(r_kind),dimension(n),intent(in) :: xp !< array of log(x)-values
1002  real(r_kind),intent(in) :: xb !< value of x
1003  real(r_kind),dimension(n),intent(in) :: yp !< array of y-values
1004  real(r_kind),intent(inout) :: res !< interpolated value of y
1005  logical,intent(in) :: flin !< flag for linear interpolation
1006  integer,intent(in) :: itype !< interpolation type
1007  !
1008  integer :: ii
1009  integer, parameter :: maxiter=50
1010  real(r_kind) :: x1,x2
1011  real(r_kind) :: m,y1,y2,xnew,b
1012  real(r_kind),parameter :: diff=1d-4
1013  real(r_kind),parameter :: tol =1d-10
1014  logical :: converged
1015 
1016 
1017  x1 = res
1018  x2=x1+diff
1019  converged = .false.
1020 
1021  inner_loop: do ii=1,maxiter
1022  ! Calculate slope
1023  call interp1d(n,yp,x1,xp,y1,flin,itype)
1024  call interp1d(n,yp,x2,xp,y2,flin,itype)
1025  y1 = y1-xb
1026  y2 = y2-xb
1027  if (x1 .ne. x2) then
1028  m = (y1-y2)/(x1-x2)
1029  else
1030  converged = .false.
1031  exit inner_loop
1032  endif
1033 
1034  ! calculate new x value
1035  b = y1-m*x1
1036 
1037  ! Exit if the slope is zero
1038  if (m .eq. 0) then
1039  converged = .false.
1040  ! Give a very large negative number
1041  exit
1042  end if
1043 
1044  xnew = -b/m
1045 
1046  ! Exit if converged
1047  if (abs(x1-xnew) .lt. tol) then
1048  converged = .true.
1049  exit inner_loop
1050  end if
1051 
1052  ! Reshuffle variables if it is not converged
1053  x1 = xnew
1054  x2 = x1+diff
1055 
1056  end do inner_loop
1057 
1058  ! Take NR value if it converged
1059  if (converged) then
1060  res = xnew
1061  else
1062  res = res
1063  end if
1064 
1065  return
1066  end subroutine inverse_nr
1067 
1068 
1069 !>
1070 !! The inverse of the 1D interpolation function.
1071 !!
1072 !! Finds the inverse of interp1d and returns the value of x using Brent's method,
1073 !! a hybrid root-finding algorithm that combines the robustness of the bisection method
1074 !! with the speed of inverse quadratic interpolation and the secant method.
1075 !! Brent's method ensures that the root is bracketed at every iteration,
1076 !! providing a reliable and efficient way to converge on the solution.
1077 !! For more details, see the
1078 !! [wikipedia](https://en.wikipedia.org/wiki/Brent%27s_method) article.
1079 !!
1080 !! @note The result depends on xb, because x_i does not necessarily have
1081 !! to be monotonic. The result should be the closest value to xb.
1082 !!
1083 !! @author M. Reichert
1084 !! @date 16.10.2024
1085 subroutine inverse_brent(n, xp, xb, yp, res, flin, itype)
1086  use error_msg_class, only: raise_exception
1087  implicit none
1088  integer, intent(in) :: n !< size of the array
1089  real(r_kind), dimension(n), intent(in) :: xp !< array of x-values
1090  real(r_kind), dimension(n), intent(in) :: yp !< array of y-values
1091  real(r_kind), intent(in) :: xb !< target x-value for root finding
1092  real(r_kind), intent(inout) :: res !< interpolated root result
1093  logical,intent(in) :: flin !< flag for linear interpolation
1094  integer,intent(in) :: itype!< interpolation type
1095  ! Internal variables
1096  real(r_kind) :: input_res
1097  real(r_kind) :: y1, y2
1098  integer :: ii
1099  real(r_kind) :: a, b, c, d, fa, fb, fc, fs, s
1100  real(r_kind) :: x1
1101  logical :: mflag, converged
1102  real(r_kind), parameter :: tol=1d-10 !< tolerance for convergence
1103  integer, parameter :: maxiter=100 !< Maximum allowed iterations
1104 
1105  ! Save the input res
1106  input_res = res
1107 
1108  ! Initialize variables
1109  ! Find value of res in yp
1110  ii = minloc(abs(yp(:)-res),dim=1)
1111 
1112  a = yp(ii) ! Assuming a starts at the index of "res"
1113  b = yp(n) ! Assuming b starts at the last x value
1114  call interp1d(n,yp,a,xp,y1,flin,itype)
1115  call interp1d(n,yp,b,xp,y2,flin,itype)
1116 
1117  fa = y1 - xb
1118  fb = y2 - xb
1119 
1120  if (fa * fb >= 0.0d0) then
1121  call raise_exception("Root must be bracketed in brents method.",&
1122  "inverse_brent", 270006)
1123  endif
1124 
1125  ! ! Swap a and b if necessary to ensure |f(a)| < |f(b)|
1126  if (abs(fa) < abs(fb)) then
1127  x1 = a
1128  a = b
1129  b = x1
1130  call interp1d(n,yp,a,xp,y1,flin,itype)
1131  call interp1d(n,yp,b,xp,y2,flin,itype)
1132  fa = y1 - xb
1133  fb = y2 - xb
1134  endif
1135 
1136  c = a
1137  fc = fa
1138  mflag = .true.
1139  d = 0.0
1140  ! Default: not converged
1141  converged = .false.
1142 
1143  ! Iteration loop
1144  do ii = 1, maxiter
1145  ! Check for convergence
1146  if (abs(fb) < tol .or. abs(b - a) < tol) then
1147  converged = .true.
1148  res = b
1149  exit
1150  endif
1151 
1152  ! Secant or inverse quadratic interpolation
1153  if (fa /= fc .and. fb /= fc) then
1154  s = a * fb * fc / ((fa - fb) * (fa - fc)) + &
1155  b * fa * fc / ((fb - fa) * (fb - fc)) + &
1156  c * fa * fb / ((fc - fa) * (fc - fb))
1157  else
1158  s = b - fb * (b - a) / (fb - fa)
1159  endif
1160 
1161  ! Check if the bisection method is needed
1162  if ((s < (3.0 * a + b) / 4.0 .or. s > b) .or. &
1163  (mflag .and. abs(s - b) >= abs(b - c) / 2.0) .or. &
1164  (.not. mflag .and. abs(s - b) >= abs(c - d) / 2.0) .or. &
1165  (mflag .and. abs(b - c) < tol) .or. &
1166  (.not. mflag .and. abs(c - d) < tol)) then
1167  ! Bisection method
1168  s = (a + b) / 2.0
1169  mflag = .true.
1170  else
1171  mflag = .false.
1172  endif
1173 
1174  ! Evaluate the function at the new point
1175  call interp1d(n,yp,s,xp,y1,flin,itype)
1176  fs = y1 - xb
1177  d = c
1178  c = b
1179  fc = fb
1180 
1181  ! Update a or b
1182  if (fa * fs < 0.0) then
1183  b = s
1184  fb = fs
1185  else
1186  a = s
1187  fa = fs
1188  endif
1189 
1190  ! Ensure |f(a)| < |f(b)|
1191  if (abs(fa) < abs(fb)) then
1192  x1 = a
1193  a = b
1194  b = x1
1195  call interp1d(n,yp,a,xp,y1,flin,itype)
1196  call interp1d(n,yp,b,xp,y2,flin,itype)
1197  fa = y1 - xb
1198  fb = y2 - xb
1199  endif
1200  end do
1201 
1202  ! Check if it converged, if not keep the input estimate
1203  if (.not. converged) then
1204  res = input_res ! Keep the previous result if no convergence
1205  endif
1206  end subroutine inverse_brent
1207 
1208 
1209 
1210 
1211 end module inter_module
inter_module
Module inter_module with interpolation routines.
Definition: inter_module.f90:13
error_msg_class
Error handling routines.
Definition: error_msg_class.f90:16
error_msg_class::int_to_str
character(:) function, allocatable, public int_to_str(num)
Converts a given integer to a string.
Definition: error_msg_class.f90:224
inter_module::cubinter
subroutine, private cubinter(n, xp, xb, yp, res, flin)
Cubic interpolation in log-log space. Here, it is assumed that.
Definition: inter_module.f90:162
inter_module::get_indice_2d
subroutine, public get_indice_2d(xval, yval, x, y, x_dim, y_dim, indices)
Get indices of the grid for given x- and y- values.
Definition: inter_module.f90:588
inter_module::inverse_brent
subroutine, private inverse_brent(n, xp, xb, yp, res, flin, itype)
The inverse of the 1D interpolation function.
Definition: inter_module.f90:1086
error_msg_class::raise_exception
subroutine, public raise_exception(msg, sub, error_code)
Raise a exception with a given error message.
Definition: error_msg_class.f90:245
inter_module::pchipinter
subroutine, private pchipinter(n, xp, xb, yp, res, flin)
PCHIP interpolation in lin-log space.
Definition: inter_module.f90:244
inter_module::interp1d
subroutine, public interp1d(n, xp, xb, yp, res, flin, itype)
Interface for 1D interpolation routines.
Definition: inter_module.f90:100
inter_module::makimainter
subroutine, private makimainter(n, xp, xb, yp, res, flin)
Interpolation using modified prescription of Akima.
Definition: inter_module.f90:482
parameter_class::interp_mode
integer interp_mode
Mode for interpolation of temperature and density.
Definition: parameter_class.f90:151
r_kind
#define r_kind
Definition: macros.h:46
inter_module::lininter
subroutine, private lininter(n, ref_array, ref_value, array, res, flin)
Linear interpolation in lin-log space.
Definition: inter_module.f90:41
inter_module::inverse_nr
subroutine, private inverse_nr(n, xp, xb, yp, res, flin, itype)
The inverse of the 1D interpolation function.
Definition: inter_module.f90:998
inter_module::cubinter_2d
real(r_kind) function, public cubinter_2d(xin, yin, x, y, f, dfx, dfy, dfxy, x_dim, y_dim, indice, extrapolation)
Cubic interpolate on 2-Dimensional grid.
Definition: inter_module.f90:796
inter_module::akimainter
subroutine, private akimainter(n, xp, xb, yp, res, flin)
Interpolation using prescription of Akima.
Definition: inter_module.f90:365
inter_module::lininter_2d
real(r_kind) function, public lininter_2d(xin, yin, x, y, f, x_dim, y_dim, indice, extrapolation)
Interpolate linearly on 2 Dimensional grid.
Definition: inter_module.f90:700
inter_module::calc_derivative_2d
subroutine, public calc_derivative_2d(f, x, y, dfx, dfy, dfxy, x_dim, y_dim)
Calculate derivatives at all points in a given grid.
Definition: inter_module.f90:624
inter_module::inverse_interp1d
subroutine, public inverse_interp1d(n, xp, xb, yp, res, flin, itype, reverse_type)
The inverse of the 1D interpolation function.
Definition: inter_module.f90:926
pi
real(r_kind) function pi()
Further information: http://netlib.org/quadpack/index.html https://orion.math.iastate....
Definition: quadpack_module.f90:193
parameter_class
Contains all runtime parameters as well as phys and math constants.
Definition: parameter_class.f90:24