laserfields
Fortran95 library to describe time-dependent laser pulses
Toggle main menu visibility
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
4
module
laserfields_miscfuncs
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
21
contains
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
!-----------------------------------------------------------------------
172
end module
laserfields_miscfuncs
cmplx
double complex cmplx
Definition
Faddeeva_c.c:226
laserfields_miscfuncs::gnuplotstring
convert real or complex numbers to strings that can be used in gnuplot
Definition
laserfields_miscfuncs.f90:16
laserfields_miscfuncs::interpolate
1-dimensional polynomial interpolation
Definition
laserfields_miscfuncs.f90:9
laserfields_miscfuncs
Definition
laserfields_miscfuncs.f90:4
laserfields_miscfuncs::binary_search
pure integer function binary_search(xs, x)
do a binary search and return index il for which xs(il) <= x <= xs(il+1)
Definition
laserfields_miscfuncs.f90:139
laserfields_miscfuncs::phase
real(dp) pure elemental function phase(c)
obtain the phase (=argument) of a complex number
Definition
laserfields_miscfuncs.f90:37
laserfields_miscfuncs::get_unused_unit
integer function get_unused_unit()
Definition
laserfields_miscfuncs.f90:24
laserfields_miscfuncs::abs2_phase
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...
Definition
laserfields_miscfuncs.f90:44
laserfields_miscfuncs::lagrange_interpol
real(dp) pure function lagrange_interpol(xk, yk, n, x)
lagrange polynomial interpolation, using the barycentric form (see e.g. wikipedia)
Definition
laserfields_miscfuncs.f90:105
nrtype
Definition
nrtype.f90:4
nrtype::dp
integer, parameter dp
Definition
nrtype.f90:6
src
laserfields_miscfuncs.f90
Generated on
for laserfields by
1.17.0