-
Notifications
You must be signed in to change notification settings - Fork 0
/
jacobitheta.f90
362 lines (308 loc) · 12.9 KB
/
jacobitheta.f90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
module jacobitheta
!!No dependencies -- this is a stand-alone application
implicit none
!imaginary unit
COMPLEX(KIND=KIND((1.0D0,1.0D0))), PARAMETER :: iunit = (0.d0, 1.d0)
!imagianry zero
COMPLEX(KIND=KIND((1.0D0,1.0D0))), PARAMETER :: czero = (0.d0, 0.d0)
!pi
real(KIND=KIND(1.0D0)), parameter :: pi=3.14159265358979323846264338327950d0
private
public :: theta1,theta2, theta3, theta4, thetagen
public :: logtheta1,logtheta2, logtheta3, logtheta4, logthetagen
contains
!! All pubblic functions map onto theta3
!! Theta 3 is then computed in logarithmic form (to avoid infinites)
!! and then transformed back to normal if needed.
!! All theta functions are (a)periodic with periodicity '1'
!!------------------------------------------------
!! Externally callable functions
!!------------------------------------------------
!! ------------------ !!! Theta 1
function theta1(z,tau,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
complex(KIND=KIND((1.0D0,1.0D0))) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dotheta1(z,tau,.FALSE.,maxiter=maxiter)
end function theta1
!! ------------------ !!! log Theta 1
function logtheta1(z,tau,maxiter) result(res) bind(C)
use ISO_C_BINDING
complex(KIND=C_DOUBLE_COMPLEX), intent(IN) :: z,tau
complex(KIND=C_DOUBLE_COMPLEX) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dotheta1(z,tau,.TRUE.,maxiter=maxiter)
end function logtheta1
!! ------------------ !!! Theta 2
complex(KIND=KIND((1.0D0,1.0D0))) function theta2(z,tau,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dotheta2(z,tau,.FALSE.,maxiter=maxiter)
end function theta2
!! ------------------ !!! log Theta 2
function logtheta2(z,tau,maxiter) result(res) bind(C)
use ISO_C_BINDING
complex(KIND=C_DOUBLE_COMPLEX), intent(IN) :: z,tau
complex(KIND=C_DOUBLE_COMPLEX) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dotheta2(z,tau,.TRUE.,maxiter=maxiter)
end function logtheta2
!! ------------------ !!! Theta 3
function theta3(z,tau,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
complex(KIND=KIND((1.0D0,1.0D0))) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dotheta3(z,tau,.FALSE.,maxiter=maxiter)
end function theta3
!! ------------------ !!! log Theta 3
function logtheta3(z,tau,maxiter) result(res) bind(C)
use ISO_C_BINDING
complex(KIND=C_DOUBLE_COMPLEX), intent(IN) :: z,tau
complex(KIND=C_DOUBLE_COMPLEX) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dotheta3(z,tau,.TRUE.,maxiter=maxiter)
end function logtheta3
!! ------------------ !!! Theta 4
function theta4(z,tau,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
complex(KIND=KIND((1.0D0,1.0D0))) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dotheta4(z,tau,.FALSE.,maxiter=maxiter)
end function theta4
!! ------------------ !!! log Theta 4
function logtheta4(z,tau,maxiter) result(res) bind(C)
use ISO_C_BINDING
complex(KIND=C_DOUBLE_COMPLEX), intent(IN) :: z,tau
complex(KIND=C_DOUBLE_COMPLEX) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dotheta4(z,tau,.TRUE.,maxiter=maxiter)
end function logtheta4
!! ------------------ !!! Theta gen
function thetagen(a,b,z,tau,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
real(KIND=KIND(1.0D0)), intent(IN) :: a,b
complex(KIND=KIND((1.0D0,1.0D0))) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
!! thetagen is periodic in a
res = dothetagen(mod(a,1.0),z+b,tau,.FALSE.,maxiter=maxiter)
end function thetagen
function logthetagen(a,b,z,tau,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
real(KIND=KIND(1.0D0)), intent(IN) :: a,b
complex(KIND=KIND((1.0D0,1.0D0))) :: res
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dothetagen(mod(a,1.0d0),z+b,tau,.TRUE.,maxiter=maxiter)
end function logthetagen
!!--------------------------------------------------
!! Internal functions
!!--------------------------------------------------
function M(z,tau) result(res)
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
complex(KIND=KIND((1.0D0,1.0D0))) :: res
res = iunit*pi*z+iunit*pi*tau/4
end function M
!! NB: Thus theta[a,b](z,tau) = theta[a,0](z+b,tau)
function dothetagen(a,z,tau,logged,maxiter) result(res)
!!thetagernal = sum_k exp(i pi tau (k+a)^2) exp(i 2 (k +a) (z+b))
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
real(KIND=KIND(1.0D0)), intent(IN) :: a
logical, intent(IN) :: logged
integer, intent(in), optional :: maxiter !!Loop counter!!
res = iunit*pi*a*(2*z+a*tau) + dologtheta3(z+a*tau,tau,maxiter=maxiter)
if(.not.logged)then
res = exp(res)
end if
end function dothetagen
function dotheta1(z,tau,logged,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
logical, intent(IN) :: logged
integer, intent(in), optional :: maxiter !!Loop counter!!
res = -iunit*pi*0.5d0 + M(z,tau) + dologtheta3(z+0.5d0+tau/2,tau,maxiter=maxiter)
if(.not.logged)then
res = exp(res)
end if
end function dotheta1
function dotheta2(z,tau,logged,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
logical, intent(IN) :: logged
integer, intent(in), optional :: maxiter !!Loop counter!!
res = M(z,tau) + dologtheta3(z+tau/2,tau,maxiter=maxiter)
if(.not.logged)then
res = exp(res)
end if
end function dotheta2
recursive function dotheta3(z,tau,logged,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
logical, intent(IN) :: logged
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dologtheta3(z,tau,maxiter=maxiter)
if(.not.logged)then
res = exp(res)
end if
end function dotheta3
recursive function dotheta4(z,tau,logged,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
logical, intent(IN) :: logged
integer, intent(in), optional :: maxiter !!Loop counter!!
res = dologtheta3(z+0.5d0,tau,maxiter=maxiter)
if(.not.logged)then
res = exp(res)
end if
end function dotheta4
!!Here we do all the modular transformations, everything is in log scale
recursive function dologtheta4(z,tau,pass_in,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
integer, intent(in), optional :: pass_in,maxiter !!Loop counter!!
integer :: passes
if(.not.present(pass_in))then
passes=1
else
passes=pass_in+1
end if
res = dologtheta3(z+0.5d0,tau,passes,maxiter=maxiter)
end function dologtheta4
recursive function dologtheta3(z,tau,pass_in,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
complex(KIND=KIND((1.0D0,1.0D0))) :: tau2,tauprime
integer, intent(in), optional :: pass_in, maxiter !!Loop counter!!
integer :: passes,local_maxiter
if(.not.present(maxiter))then
local_maxiter=1000
else
local_maxiter=maxiter
end if
if(.not.present(pass_in))then
passes=1
else
passes=pass_in+1
end if
if(passes.gt.local_maxiter)then
!! STDERR = 0 !!
write(*,*) 'ERROR: More than ',local_maxiter,' modular transformations have been performed!'
write(*,*) ' This can happen if tau is faar from the fundamental domain!'
write(*,*) ' Either increase maxiter or find perform some transformations by hand...'
write(*,*) ' Input z =',z
write(*,*) ' Input tau=',tau
call exit(-1)
end if
!!write(*,*) ' passes =',passes
!!write(*,*) ' First Input z =',z
!!write(*,*) ' FIrst Input tau=',tau
!!Check that computation has a chance of converging
!! STDERR = 0 !!
if(Aimag(tau).le.0.d0)then
write(0,*) 'ERROR JACOBI THETA:'
write(0,*) 'Attempting to evaluate the function with Im(tau)<=0'
write(0,*) 'tau=',tau
write(0,*) 'This can never converge, quitting...'
call exit(-1)
end if
!!Initaite to avoid compiler warning
tau2=tau
!! This should put tau in the principal region (approx)
! If |Re(tau)| > 1 shift to |Re(tau)|<1
if(REAL(tau).ge.(0.d0)) then
tau2 = mod(real(tau+1),2.d0)-1 + iunit*aimag(tau)
elseif(REAL(tau).lt.(0.d0)) then
tau2 = mod(real(tau-1),2.d0)+1 + iunit*aimag(tau)
end if
! if |Re(tau)| > .6 shift to |Re(tau)| < .6, here theta3 -> theta4
if(REAL(tau2).gt.(6.d-1)) then
res = dologtheta4(z,tau2-1,passes,maxiter=local_maxiter) !! Shift back
elseif(REAL(tau2).le.(-(6.d-1))) then
res = dologtheta4(z,tau2+1,passes,maxiter=local_maxiter) !! shift forward
! if |tau| < 1 invert to make |tau| > 1
!!NB: There is a risk that the finite presition will cause both |tau|<1 and |1/tau|<1.
!!tau =(-4.8751486325802507d-2, 0.99881093935790721d0) is such a case!!
!!We are then content with tau2<0.98 since this will converet almost as fast anyway.
elseif((ABS(tau2).lt.0.98d0).AND.(AIMAG(tau2).lt.0.98d0)) then
!! If tau is small. Invert
tauprime=-1.0d0/tau2
res = iunit*pi*tauprime*z**2 &
+ dologtheta3(z*tauprime,tauprime,passes,maxiter=local_maxiter) &
- log(sqrt(-iunit*tau2)) !! invert
else
res = argtheta3(z,tau2,maxiter=local_maxiter)
end if
end function dologtheta3
recursive function argtheta3(z,tau,pass_in,maxiter) result(res)
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
complex(KIND=KIND((1.0D0,1.0D0))) :: zuse,zmin
integer, intent(in), optional :: pass_in, maxiter !!Loop counter!!
integer :: passes,local_maxiter
integer :: quotient
if(.not.present(maxiter))then
local_maxiter=10
else
local_maxiter=maxiter
end if
if(.not.present(pass_in))then
passes=1
else
passes=pass_in+1
end if
!write(*,*) ' passes =',passes
!write(*,*) ' Input z =',z
!write(*,*) ' Input tau=',tau
if(passes.gt.local_maxiter)then
write(*,*) 'ERROR: More than ',local_maxiter,' shifts of z have been performed!'
write(*,*) ' This should not happen! Please file a bug report!'
write(*,*) ' Input z =',z
write(*,*) ' Input tau=',tau
call exit(-1)
end if
!!Reduce -0.5 < Re(z) < 0.5
zuse = mod(real(z),1.d0) + iunit*aimag(z)
!write(*,*) '---- ',zuse
!Swith the sign of z if the iunit part is negative
if(AIMAG(zuse).lt.(-AIMAG(tau)/2)) then
res = argtheta3(-zuse,tau,passes,maxiter=local_maxiter)
!!If the argument is to large, shift it away
elseif(AIMAG(zuse).ge.(AIMAG(tau)/2)) then
!!write(*,*) 'The quotient is',AIMAG(zuse)/AIMAG(tau)
quotient = floor(AIMAG(zuse)/AIMAG(tau)+.5) !!!also automatic flooring
!!write(*,*) 'The floor is',quotient
zmin = zuse-tau*quotient
res = -2*pi*quotient*iunit*zmin + argtheta3(zmin,tau,passes,maxiter=local_maxiter) - iunit*pi*tau*quotient*quotient
else
res = calctheta3(zuse,tau)
end if
end function argtheta3
function calctheta3(z,tau) result(res)
complex(KIND=KIND((1.0D0,1.0D0))) :: res
complex(KIND=KIND((1.0D0,1.0D0))), intent(IN) :: z,tau
complex(KIND=KIND((1.0D0,1.0D0))) :: q,qweight
integer :: n
q = exp(iunit*pi*tau)
res = (1.d0,0.d0)
n=0
do
n = n + 1
!!OBS splitting qweight=2*q**(n**2)*cos(2*n*z) into two expontentials to get around lage numbers
qweight=exp(iunit*n*pi*(tau*n+2*z))+exp(iunit*n*pi*(tau*n-2*z))
res = res + qweight
!! Terminate on convergence (or NaNs or Zeroes)
if( isnan(abs(res))) then
write(*,*) 'ERROR: Value is infinite in theta function'
write(*,*) 'z,tau:',z,tau
call exit(-1)
elseif( abs(res).eq.0.d0 ) then
write(*,*) 'Value is zero'
exit
elseif((n.ge.3).and.((res+qweight).eq.res)) then
!!Converged to within machine precision
exit
end if
end do
!!Take log on number (to avoid eventual divergentices in the erlier transformations)
res=log(res)
end function calctheta3
end module jacobitheta