laserfields
Fortran95 library to describe time-dependent laser pulses
Loading...
Searching...
No Matches
laserfields_miscfuncs.f90
Go to the documentation of this file.
1! Copyright (c) 2012, Johannes Feist
2! licensed under the MIT open source license, see LICENSE file
3
5 use nrtype
6 implicit none
7
8 !> 1-dimensional polynomial interpolation
9 interface interpolate
10 module procedure interpolate_single
11 module procedure interpolate_array
12 end interface
13 private interpolate_array, interpolate_single
14
15 !> convert real or complex numbers to strings that can be used in gnuplot
16 interface gnuplotstring
17 module procedure gnuplotstring_d
18 module procedure gnuplotstring_z
19 end interface
20 private gnuplotstring_d, gnuplotstring_z
21contains
22 !---------------------------------------------------------------------------
23 function get_unused_unit() result(unit)
24 integer :: unit
25 logical :: opened
26 ! find an unused unit to use
27 unit = 16
28 opened = .true.
29 do while (opened)
30 unit = unit + 1
31 inquire(unit=unit,opened=opened)
32 end do
33 end function get_unused_unit
34 !----------------------------------------------------------------------
35 !> obtain the phase (=argument) of a complex number
36 real(dp) pure elemental function phase(c)
37 complex(dpc), intent(in) :: c
38 phase = atan2(aimag(c),real(c))
39 end function phase
40 !---------------------------------------------------------------------------
41 !> return a complex number containing absolute value squared and phase
42 !> as real and imaginary part: {|c|<sup>2</sup>,phase(c)}
43 complex(dpc) pure elemental function abs2_phase(c)
44 complex(dpc), intent(in) :: c
45 abs2_phase = cmplx(abs(c)**2,phase(c),dpc)
46 end function abs2_phase
47 !---------------------------------------------------------------------------
48 !> converts a double to a character string for gnuplot
49 character(15) function gnuplotstring_d(val) result(ch)
50 real(dp), intent(in) :: val
51 write(ch,'(sp,es15.8)') val
52 end function gnuplotstring_d
53 !---------------------------------------------------------------------------
54 !> converts a double complex to a character string for gnuplot
55 character(33) function gnuplotstring_z(val) result(ch)
56 complex(dpc), intent(in) :: val
57 write(ch,'(sp,a,es15.8,a,es15.8,a)') '{',real(val),',',aimag(val),'}'
58 end function gnuplotstring_z
59 !---------------------------------------------------------------------------
60 !> for a set of known values (x_old,f_old) calculate the value of f(x) at
61 !> point x_new using polynomial interpolation
62 real(dp) function interpolate_single(x_old,f_old,x_new,degree) result(f_new)
63 real(dp), dimension(:), intent(in) :: x_old,f_old
64 real(dp), intent(in) :: x_new
65 !> order of the interpolating polynomial
66 integer, intent(in) :: degree
67 real(dp), dimension(1) :: x_new_arr, f_new_arr
68 x_new_arr(1) = x_new
69 f_new_arr = interpolate(x_old,f_old,x_new_arr,degree)
70 f_new = f_new_arr(1)
71 end function interpolate_single
72 !---------------------------------------------------------------------------
73 !> for a set of known values (x_old,f_old) calculate the values of f(x) at
74 !> points x_new using polynomial interpolation
75 function interpolate_array(x_old,f_old,x_new,degree) result(f_new)
76 real(dp), dimension(:), intent(in) :: x_old, f_old, x_new
77 real(dp), dimension(size(x_new)) :: f_new
78 !> order of the interpolating polynomial
79 integer, intent(in) :: degree
80 integer :: ii, npoints_old, npoints_new, nearest_node, spoint, npoints_int
81
82 if (size(x_old)/=size(f_old)) stop 'ERROR: number of nodes and function values do not agree in interpolate!'
83
84 npoints_new = size(x_new)
85 npoints_old = size(x_old)
86 ! number of points used for interpolation
87 npoints_int=degree+1
88
89 do ii = 1, npoints_new
90 if (x_new(ii) < x_old(1) .or. x_new(ii) > x_old(npoints_old)) then
91 stop 'ERROR: extrapolation would be necessary in interpolate!'
92 end if
93
94 ! get nearest node smaller then x_new(ii)
95 nearest_node = binary_search(x_old,x_new(ii))
96 ! get starting point for interpolation
97 spoint = min(max(nearest_node-(npoints_int-1)/2,1),npoints_old+1-npoints_int)
98 ! call interpolation routine
99 f_new(ii) = lagrange_interpol(x_old(spoint:spoint+degree),f_old(spoint:spoint+degree),npoints_int,x_new(ii))
100 end do
101 end function interpolate_array
102 !-----------------------------------------------------------------------
103 !> lagrange polynomial interpolation, using the barycentric form (see e.g. wikipedia)
104 real(dp) pure function lagrange_interpol(xk,yk,n,x) result(y)
105 !> size of xk and yk.
106 integer, intent(in) :: n
107 !> x-values of points to interpolate.
108 real(dp), intent(in) :: xk(n)
109 !> y-values of points to interpolate.
110 real(dp), intent(in) :: yk(n)
111 !> position at which to evaluate the interpolating polynomial.
112 real(dp), intent(in) :: x
113 real(dp) :: wk(n), nom, denom, diff
114 integer :: ii, jj
115 do jj = 1, n
116 wk(jj) = 1
117 do ii = 1, n
118 if (ii/=jj) wk(jj) = wk(jj) / (xk(jj)-xk(ii))
119 end do
120 end do
121 nom = 0
122 denom = 0
123 do jj = 1, n
124 diff = abs(x-xk(jj))
125 ! this guards against x=xk(jj)=0
126 if (diff/=0) diff = 2*diff / (abs(x)+abs(xk(jj)))
127 if (diff < 1.e-12) then
128 y = yk(jj)
129 return
130 end if
131 nom = nom + wk(jj)*yk(jj) / (x - xk(jj))
132 denom = denom + wk(jj) / (x - xk(jj))
133 end do
134 y = nom/denom
135 end function lagrange_interpol
136 !-----------------------------------------------------------------------
137 !> do a binary search and return index il for which xs(il) <= x <= xs(il+1)
138 pure integer function binary_search(xs,x) result(il)
139 !> input array to search, has to be sorted (either in ascending or descending order)
140 real(dp), intent(in) :: xs(:)
141 !> value to search for
142 real(dp), intent(in) :: x
143 integer :: n, im, iu
144 logical :: increasing
145
146 n = size(xs)
147 ! we do not check whether the sequence is actually monotonic, but we handle increasing and decreasing sequences
148 increasing = xs(1) < xs(n)
149
150 if (increasing) then
151 if (x < xs(1)) then; il = 1; return
152 else if (x > xs(n)) then; il = n; return
153 end if
154 else
155 if (x > xs(1)) then; il = 1; return
156 else if (x < xs(n)) then; il = n; return
157 end if
158 end if
159
160 il=0 ! initial value for lower border
161 iu=n+1 ! initial value for upper border
162 do while (iu-il>1)
163 im=(iu+il)/2
164 if (increasing.eqv.(x > xs(im))) then
165 il=im
166 else
167 iu=im
168 end if
169 end do
170 end function binary_search
171 !-----------------------------------------------------------------------
172end module laserfields_miscfuncs
double complex cmplx
Definition Faddeeva_c.c:226
convert real or complex numbers to strings that can be used in gnuplot
1-dimensional polynomial interpolation
pure integer function binary_search(xs, x)
do a binary search and return index il for which xs(il) <= x <= xs(il+1)
real(dp) pure elemental function phase(c)
obtain the phase (=argument) of a complex number
integer function get_unused_unit()
complex(dpc) pure elemental function abs2_phase(c)
return a complex number containing absolute value squared and phase as real and imaginary part: {|c|2...
real(dp) pure function lagrange_interpol(xk, yk, n, x)
lagrange polynomial interpolation, using the barycentric form (see e.g. wikipedia)
integer, parameter dp
Definition nrtype.f90:6