Branch data Line data Source code
1 : : !!****m* ABINIT/m_cutoff_cylinder
2 : : !! NAME
3 : : !! m_cutoff_cylinder
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !! SOURCE
8 : :
9 : : #if defined HAVE_CONFIG_H
10 : : #include "config.h"
11 : : #endif
12 : :
13 : : #include "abi_common.h"
14 : :
15 : : module m_cutoff_cylinder
16 : :
17 : : use defs_basis
18 : : use m_abicore
19 : : use m_errors
20 : : use m_xmpi
21 : : use m_splines
22 : : use m_sort
23 : :
24 : : use m_fstrings, only : sjoin, itoa
25 : : use m_geometry, only : normv, metric
26 : : use m_bessel, only : CALJY0, CALJY1, CALCK0, CALCK1
27 : : use m_numeric_tools, only : OPERATOR(.x.), quadrature
28 : : use m_paw_numeric, only : paw_jbessel
29 : :
30 : : implicit none
31 : :
32 : : private
33 : : !!***
34 : :
35 : : public :: cutoff_cylinder, K0cos
36 : :
37 : : !integer,public,parameter :: CYLINDER_BEIGI = 1
38 : : !integer,public,parameter :: CYLINDER_ROZZI = 2
39 : : !!***
40 : :
41 : : ! private variables used for the integration needed by the cylindrical case.
42 : : integer,save :: npts_,ntrial_,qopt_
43 : : real(dp),save :: ha_,hb_,r0_
44 : : real(dp),save :: qpg_perp_,qpg_para_,qpgx_,qpgy_
45 : : real(dp),save :: zz_,xx_, rho_
46 : : real(dp),save :: hcyl_,rcut_,accuracy_
47 : :
48 : : CONTAINS
49 : : !!***
50 : :
51 : : !----------------------------------------------------------------------
52 : :
53 : : !!****f* ABINIT/cutoff_cylinder
54 : : !! NAME
55 : : !! cutoff_cylinder
56 : : !!
57 : : !! FUNCTION
58 : : !! Calculate the Fourier components of an effective Coulomb interaction
59 : : !! zeroed outside a finite cylindrical region. Two methods are implemented:
60 : : !!
61 : : !! method==1: The interaction in the (say) x-y plane is truncated outside the Wigner-Seitz
62 : : !! cell centered on the wire in the x-y plane. The interaction has infinite
63 : : !! extent along the z axis and the Fourier transform is singular only at the Gamma point.
64 : : !! Only orthorombic Bravais lattices are supported.
65 : : !! method==2: The interaction is truncated outside a cylinder of radius rcut. The cylinder has finite
66 : : !! extent along z. No singularity occurs.
67 : : !!
68 : : !! INPUTS
69 : : !! boxcenter(3)= center of the wire in the x-y axis
70 : : !! qpt(3)= q-point
71 : : !! ng=number of G vectors
72 : : !! gvec(3,ng)=G vectors in reduced coordinates
73 : : !! rprimd(3,3)=dimensional real space primitive translations (bohr)
74 : : !! method=1 for Beigi approach (infinite cylinder with interaction truncated outside the W-S cell)
75 : : !! 2 for Rozzi method (finite cylinder)
76 : : !! comm=MPI communicator.
77 : : !!
78 : : !! OUTPUT
79 : : !! vc_cut(ng)= Fourier components of the effective Coulomb interaction
80 : : !!
81 : : !! SOURCE
82 : :
83 : 112 : subroutine cutoff_cylinder(qpt, ng, gvec, rcut, hcyl, pdir, boxcenter, rprimd, vc_cut, method, comm)
84 : :
85 : : !Arguments ------------------------------------
86 : : !scalars
87 : : integer,intent(in) :: ng,method,comm
88 : : real(dp),intent(in) :: rcut,hcyl
89 : : !arrays
90 : : integer,intent(in) :: gvec(3,ng),pdir(3)
91 : : real(dp),intent(in) :: boxcenter(3),qpt(3),rprimd(3,3)
92 : : real(dp),intent(out) :: vc_cut(ng)
93 : :
94 : : !Local variables-------------------------------
95 : : !scalars
96 : : integer,parameter :: N0=1000
97 : : integer :: ig,igs,ierr, my_rank, nproc
98 : : real(dp) :: j0,j1,k0,k1,qpg2,qpg_xy,tmp
99 : : real(dp) :: qpg_z,quad,rcut2,hcyl2,c1,c2,ucvol,SMALL
100 : : logical :: q_is_zero
101 : : character(len=500) :: msg
102 : : !arrays
103 : : real(dp) :: qpg(3),b1(3),b2(3),b3(3),gmet(3,3),rmet(3,3),gprimd(3,3),qc(3),gcart(3)
104 : : !************************************************************************
105 : :
106 : : ABI_UNUSED(pdir)
107 : : ABI_UNUSED(boxcenter)
108 : :
109 : : ! ===================================================
110 : : ! === Setup for the quadrature of matrix elements ===
111 : : ! ===================================================
112 : 112 : qopt_ =6 ! Quadrature method, see quadrature routine.
113 : 112 : ntrial_ =30 ! Max number of attempts.
114 : 112 : accuracy_=0.001 ! Fractional accuracy required.
115 : 112 : npts_ =6 ! Initial number of point (only for Gauss-Legendre method).
116 : 112 : SMALL =tol4 ! Below this value (q+G)_i is treated as zero.
117 : 112 : rcut_ =rcut ! Radial cutoff, used only if method==2
118 : 112 : hcyl_ =hcyl ! Lenght of cylinder along z, only if method==2
119 : :
120 : : !write(msg,'(3a,2(a,i5,a),a,f8.5)')ch10,&
121 : : ! ' cutoff_cylinder: Info on the quadrature method : ',ch10,&
122 : : ! ' Quadrature scheme = ',qopt_,ch10,&
123 : : ! ' Max number of attempts = ',ntrial_,ch10,&
124 : : ! ' Fractional accuracy = ',accuracy_
125 : : !call wrtout(std_out, msg)
126 : :
127 : : ! From reduced to Cartesian coordinates.
128 : 112 : call metric(gmet, gprimd, -1, rmet, rprimd, ucvol)
129 [ + + ]: 448 : b1(:) =two_pi*gprimd(:,1)
130 [ + + ]: 448 : b2(:) =two_pi*gprimd(:,2)
131 [ + + ]: 448 : b3(:) =two_pi*gprimd(:,3)
132 : :
133 [ + + ]: 448 : qc = b1(:)*qpt(1) + b2(:)*qpt(2) + b3(:)*qpt(3)
134 : :
135 : 112 : my_rank = xmpi_comm_rank(comm); nproc = xmpi_comm_size(comm)
136 : :
137 : : ! ================================================
138 : : ! === Different approaches according to method ===
139 : : ! ================================================
140 [ + + ]: 1640 : vc_cut = zero
141 : :
142 : 112 : select case (method)
143 : :
144 : : case (1)
145 : : ! Infinite cylinder, interaction is zeroed outside the Wigner-Seitz cell.
146 : : ! NB: Beigi's expression holds only if the BZ is sampled only along z.
147 : : !call wrtout(std_out, 'cutoff_cylinder: Using Beigi''s Infinite cylinder')
148 : :
149 [ + + + - : 318 : if (ANY(qc(1:2) > SMALL)) then
- + ]
150 : : write(msg,'(5a)')&
151 : 0 : ' found q-points with non zero components in the X-Y plane. ',ch10,&
152 : 0 : ' This is not allowed, see Notes in cutoff_cylinder.F90. ',ch10,&
153 : 0 : ' ACTION: Modify the q-point sampling. '
154 : 0 : ABI_ERROR(msg)
155 : : end if
156 : :
157 : : ! Check if Bravais lattice is orthorombic and parallel to the Cartesian versors.
158 : : ! In this case the intersection of the WS cell with the x-y plane is a rectangle with -ha_<=x<=ha_ and -hb_<=y<=hb_
159 : : if ((ANY(ABS(rprimd(2:3, 1)) > tol6)) .or. &
160 [ + + + - : 954 : (ANY(ABS(rprimd(1:3:2,2)) > tol6)) .or. &
+ + + - +
+ + - + -
- + ]
161 : : (ANY(ABS(rprimd(1:2, 3)) > tol6))) then
162 : 0 : ABI_ERROR('Bravais lattice should be orthorombic and parallel to the Cartesian versors')
163 : : end if
164 : :
165 [ + + + + : 424 : ha_ = half*NORM2(rprimd(:,1))
+ - ]
166 [ + + + + : 424 : hb_ = half*NORM2(rprimd(:,2))
+ - ]
167 : 106 : r0_ = MIN(ha_,hb_)/N0
168 : :
169 : : ! For each (q,G) pair evaluate the integral defining the Coulomb cutoff.
170 : : ! NB: the code assumes that all q-vectors are non zero and q_xy/=0.
171 : 106 : igs=1
172 : : ! Skip singularity at Gamma, it will be treated "by hand" in csigme.
173 : 106 : q_is_zero = (normv(qpt, gmet, 'G') < tol4)
174 : :
175 [ + + ]: 920 : do ig=igs,ng
176 [ - + ]: 814 : if (mod(ig, nproc) /= my_rank) cycle ! MPI parallelism
177 : :
178 [ + + ]: 3256 : gcart(:)=b1(:)*gvec(1,ig)+b2(:)*gvec(2,ig)+b3(:)*gvec(3,ig)
179 [ + + ]: 3256 : qpg(:)=qc(:)+gcart(:)
180 : 814 : qpgx_=qpg(1); qpgy_=qpg(2); qpg_para_=ABS(qpg(3))
181 : : !write(std_out,*)"qpgx_=",qpgx_, "qpgy_=",qpgy_, "qpg_para=",qpg_para_
182 : :
183 : : ! Avoid singularity in K_0{qpg_para_\rho) by using a small q along the periodic dimension.
184 [ + + + + ]: 814 : if (q_is_zero .and. qpg_para_ < tol6) qpg_para_ = tol6
185 : :
186 : : ! Calculate $ 2\int_{WS} dxdy K_0{qpg_para_\rho) cos(x.qpg_x + y.qpg_y) $
187 : : ! where WS is the Wigner-Seitz cell.
188 : 814 : tmp=zero
189 : :
190 : : ! Difficult part, integrate on a small cirle of radius r0 using spherical coordinates
191 : : !call quadrature(K0cos_dth_r0,zero,r0_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
192 : : !ABI_CHECK(ierr == 0, "Accuracy not reached")
193 : : !write(std_out,'(i8,a,es14.6)')ig,' 1 ',quad
194 : : !tmp=tmp+quad
195 : : ! Add region with 0<=x<=r0 and y>=+-(SQRT(r0^2-x^2))since WS is rectangular
196 : : !call quadrature(K0cos_dy_r0,zero,r0_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
197 : : !ABI_CHECK(ierr == 0, "Accuracy not reached")
198 : : !write(std_out,'(i8,a,es14.6)')ig,' 2 ',quad
199 : : !tmp=tmp+quad
200 : : ! Get the in integral in the rectangle with x>=r0, should be the easiest but sometimes has problems to converge
201 : : !call quadrature(K0cos_dy,r0_,ha_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
202 : : !ABI_CHECK(ierr == 0, "Accuracy not reached")
203 : : !write(std_out,'(i8,a,es14.6)')ig,' 3 ',quad
204 : : !
205 : : ! More stable method: midpoint integration with Romberg extrapolation ===
206 : 814 : call quadrature(K0cos_dy,zero,ha_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
207 : : !write(std_out,'(i8,a,es14.6)')ig,' 3 ',quad
208 [ - + ]: 814 : ABI_CHECK(ierr == 0, "Accuracy not reached in quadrature!")
209 : :
210 : : ! Store final result
211 : : ! Factor two comes from the replacement WS -> (1,4) quadrant thanks to symmetries of the integrad.
212 : 814 : tmp = tmp+quad
213 : 920 : vc_cut(ig) = two*(tmp*two)
214 : : end do ! ig
215 : :
216 : : case (2)
217 : : ! Finite cylinder of length hcyl from Rozzi et al.
218 : : ! TODO add check on hcyl value that should be smaller that 1/deltaq
219 [ - + ]: 6 : if (hcyl_ < zero) then
220 : 0 : write(msg,'(a,f8.4)')' Negative value for cylinder length hcyl_=',hcyl_
221 : 0 : ABI_BUG(msg)
222 : : end if
223 : :
224 [ + - ]: 6 : if (ABS(hcyl_) > tol12) then
225 : : !write(std_out,'(2(a,f8.4))')' cutoff_cylinder: using finite cylinder of length= ',hcyl_,' rcut= ',rcut_
226 : 6 : hcyl2=hcyl_**2
227 : 6 : rcut2=rcut_**2
228 : :
229 : : ! No singularity occurs in finite cylinder, thus start from 1.
230 [ + + ]: 720 : do ig=1,ng
231 [ + - ]: 714 : if (mod(ig, nproc) /= my_rank) cycle ! MPI parallelism
232 : :
233 [ + + ]: 2856 : gcart(:)=b1(:)*gvec(1,ig)+b2(:)*gvec(2,ig)+b3(:)*gvec(3,ig)
234 [ + + ]: 2856 : qpg(:)=qc(:)+gcart(:)
235 : 714 : qpg_para_=ABS(qpg(3)) ; qpg_perp_=SQRT(qpg(1)**2+qpg(2)**2)
236 : :
237 [ + + + + ]: 720 : if (qpg_perp_ /= zero .and. qpg_para_ /= zero) then
238 : : ! $ 4\pi\int_0^{R_c} d\rho\rho j_o(qpg_perp_.\rho)\int_0^hcyl dz\cos(qpg_para_*z)/sqrt(\rho^2+z^2) $
239 : 655 : call quadrature(F2,zero,rcut_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
240 [ - + ]: 655 : ABI_CHECK(ierr == 0, "Accuracy not reached")
241 : 655 : vc_cut(ig) = four_pi*quad
242 : :
243 [ + + + + ]: 59 : else if (qpg_perp_ == zero .and. qpg_para_ /= zero) then
244 : : ! $ \int_0^h sin(qpg_para_.z)/\sqrt(rcut^2+z^2)dz $
245 : 14 : call quadrature(F3,zero,hcyl_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
246 [ - + ]: 14 : ABI_CHECK(ierr == 0, "Accuracy not reached")
247 : :
248 : 14 : c1=one/qpg_para_**2-COS(qpg_para_*hcyl_)/qpg_para_**2-hcyl_*SIN(qpg_para_*hcyl_)/qpg_para_
249 : 14 : c2=SIN(qpg_para_*hcyl_)*SQRT(hcyl2+rcut2)
250 : 14 : vc_cut(ig) = four_pi*c1+four_pi*(c2-quad)/qpg_para_
251 : :
252 [ + + + - ]: 45 : else if (qpg_perp_ /= zero .and. qpg_para_ == zero) then
253 : : ! $ 4pi\int_0^rcut d\rho \rho J_o(qpg_perp_.\rho) ln((h+\sqrt(h^2+\rho^2))/\rho) $
254 : 44 : call quadrature(F4,zero,rcut_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
255 [ - + ]: 44 : ABI_CHECK(ierr == 0, "Accuracy not reached")
256 : 44 : vc_cut(ig) = four_pi*quad
257 : :
258 [ + - + - ]: 1 : else if (qpg_perp_ == zero .and. qpg_para_ == zero) then
259 : : ! Use lim q+G --> 0
260 : 1 : vc_cut(ig) = two_pi*(-hcyl2+hcyl_*SQRT(hcyl2+rcut2)+rcut2*LOG((hcyl_+SQRT(hcyl_+SQRT(hcyl2+rcut2)))/rcut_))
261 : :
262 : : else
263 : 0 : ABI_BUG('You should not be here!')
264 : : end if
265 : :
266 : : end do !ig
267 : :
268 : : else
269 : : ! Infinite cylinder.
270 : : !call wrtout(std_out, ' cutoff_cylinder: using Rozzi''s method with infinite cylinder ')
271 : :
272 [ # # ]: 0 : do ig=1,ng
273 [ # # ]: 0 : if (mod(ig, nproc) /= my_rank) cycle ! MPI parallelism
274 : :
275 [ # # ]: 0 : gcart(:)=b1(:)*gvec(1,ig)+b2(:)*gvec(2,ig)+b3(:)*gvec(3,ig)
276 [ # # ]: 0 : qpg(:)=qc(:)+gcart(:)
277 [ # # ]: 0 : qpg2 =DOT_PRODUCT(qpg,qpg)
278 : 0 : qpg_z =ABS(qpg(3)) ; qpg_xy=SQRT(qpg(1)**2+qpg(2)**2)
279 : :
280 [ # # ]: 0 : if (qpg_z > SMALL) then
281 : : ! Analytic expression.
282 : 0 : call CALCK0(qpg_z *rcut_, k0, 1)
283 : 0 : call CALJY1(qpg_xy*rcut_, j1, 0)
284 : 0 : call CALJY0(qpg_xy*rcut_, j0, 0)
285 : 0 : call CALCK1(qpg_z *rcut_, k1, 1)
286 : 0 : vc_cut(ig) = (four_pi/qpg2)*(one+rcut_*qpg_xy*j1*k0-qpg_z*rcut_*j0*k1)
287 : : else
288 [ # # ]: 0 : if (qpg_xy > SMALL) then
289 : : ! Integrate r*Jo(G_xy r)log(r) from 0 up to rcut_
290 : 0 : call quadrature(F5,zero,rcut_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
291 [ # # ]: 0 : ABI_CHECK(ierr == 0, "Accuracy not reached")
292 : 0 : vc_cut(ig)=-four_pi*quad
293 : : else
294 : : ! Analytic expression
295 : 0 : vc_cut(ig)=-pi*rcut_**2*(two*LOG(rcut_)-one)
296 : : end if
297 : : end if
298 : : end do ! ig
299 : : end if !finite/infinite
300 : :
301 : : case default
302 [ + + - ]: 112 : ABI_BUG(sjoin('Wrong value for method:',itoa(method)))
303 : : end select
304 : :
305 : : ! Collect vc_cut on each core
306 : 112 : call xmpi_sum(vc_cut, comm, ierr)
307 : :
308 : 112 : end subroutine cutoff_cylinder
309 : : !!***
310 : :
311 : : !----------------------------------------------------------------------
312 : :
313 : 4297455 : real(dp) function F1(rho)
314 : :
315 : : real(dp),intent(in) :: rho
316 : :
317 : : !Local variables-------------------------------
318 : : integer,parameter :: order=0,ll=0
319 : : real(dp) :: arg,bes,besp,bespp
320 : : !************************************************************************
321 : :
322 : : ! F1(\rho;z)= \rho*j_o(qpg_perp_*\rho)/sqrt(\rho**2+z**2)
323 : 4297455 : arg=rho*qpg_perp_
324 : 4297455 : call paw_jbessel(bes,besp,bespp,ll,order,arg)
325 : :
326 [ - + ]: 4297455 : if (zz_==zero) then
327 : 0 : F1=bes
328 : : else
329 : 4297455 : F1=bes*rho/SQRT(rho**2+zz_**2)
330 : : end if
331 : :
332 : 4297455 : end function F1
333 : : !!***
334 : :
335 : : !----------------------------------------------------------------------
336 : :
337 : 53055 : function F2(xx)
338 : :
339 : : real(dp),intent(in) :: xx
340 : : real(dp) :: F2
341 : :
342 : : !Local variables-------------------------------
343 : : !scalars
344 : : integer :: ierr
345 : : real(dp) :: intr
346 : : !************************************************************************
347 : :
348 : 53055 : zz_=xx
349 : 53055 : call quadrature(F1,zero,rcut_,qopt_,intr,ierr,ntrial_,accuracy_,npts_)
350 [ - + ]: 53055 : ABI_CHECK(ierr == 0, "Accuracy not reached")
351 : :
352 : 53055 : F2=intr*COS(qpg_para_*xx)
353 : :
354 : 53055 : end function F2
355 : : !!***
356 : :
357 : : !----------------------------------------------------------------------
358 : :
359 : 1134 : real(dp) pure function F3(xx)
360 : :
361 : : real(dp),intent(in) :: xx
362 : :
363 : : !************************************************************************
364 : :
365 : : ! F3(z)=z*\sin(qpg_para_*z)/\sqrt(rcut^2+z^2)
366 : 1134 : F3=xx*SIN(qpg_para_*xx)/SQRT(rcut_**2+xx**2)
367 : :
368 : 1134 : end function F3
369 : : !!***
370 : :
371 : : !----------------------------------------------------------------------
372 : :
373 : 3564 : real(dp) function F4(rho)
374 : :
375 : : real(dp),intent(in) :: rho
376 : :
377 : : !Local variables-------------------------------
378 : : integer,parameter :: order=0,ll=0
379 : : real(dp) :: arg,bes,besp,bespp
380 : : !************************************************************************
381 : :
382 : : ! $F4(rho)=\rho*j_o(qpg_perp_.\rho) \ln((hcyl+\sqrt(rho^2+hcyl^2))/\rho)$
383 [ + - ]: 3564 : if (ABS(rho)<tol12) then
384 : : F4=zero
385 : : else
386 : 3564 : arg=rho*qpg_perp_
387 : 3564 : call paw_jbessel(bes,besp,bespp,ll,order,arg)
388 : 3564 : F4=bes*rho*LOG((hcyl_+SQRT(rho**2+hcyl_**2))/rho)
389 : : end if
390 : :
391 : 3564 : end function F4
392 : : !!***
393 : :
394 : : !----------------------------------------------------------------------
395 : :
396 : 0 : real(dp) function F5(rho)
397 : :
398 : : real(dp),intent(in) :: rho
399 : :
400 : : !Local variables-------------------------------
401 : : integer,parameter :: order = 0, ll = 0
402 : : real(dp) :: arg,bes,besp,bespp
403 : : !************************************************************************
404 : :
405 : : ! $F5(\rho)=\rho*j_o(G_perp\rho)log(\rho)$
406 [ # # ]: 0 : if (rho==0) then
407 : : F5=zero
408 : : else
409 : 0 : arg=rho*qpg_perp_
410 : 0 : call paw_jbessel(bes,besp,bespp,ll,order,arg)
411 : 0 : F5=bes*rho*LOG(rho)
412 : : end if
413 : :
414 : 0 : end function F5
415 : : !!***
416 : :
417 : : !----------------------------------------------------------------------
418 : :
419 : 5345190 : real(dp) function K0cos(yy)
420 : :
421 : : real(dp),intent(in) :: yy
422 : :
423 : : !Local variables-------------------------------
424 : : real(dp) :: k0,rho,arg
425 : : !************************************************************************
426 : :
427 : : ! K0cos(y)=K0(\rho*|qpg_z|)*COS(x.qpg_x+y*qpg_y)
428 : 5345190 : rho=SQRT(xx_**2+yy**2) ; arg=qpg_para_*rho
429 : 5345190 : call CALCK0(arg,k0,1)
430 : 5345190 : K0cos=k0*COS(qpgx_*xx_+qpgy_*yy)
431 : :
432 : 5345190 : end function K0cos
433 : : !!***
434 : :
435 : : !----------------------------------------------------------------------
436 : :
437 : 65934 : real(dp) function K0cos_dy(xx)
438 : :
439 : : real(dp),intent(in) :: xx
440 : :
441 : : !Local variables-------------------------------
442 : : integer :: ierr
443 : : real(dp) :: quad
444 : : !************************************************************************
445 : :
446 : : !! K0cos_dy(x)=\int_{-b/2}^{b/2} K0(|qpg_z|\rho)cos(x.qpg_x+y.qpg_y)dy$
447 : 65934 : xx_=xx
448 : 65934 : call quadrature(K0cos,-hb_,+hb_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
449 [ - + ]: 65934 : ABI_CHECK(ierr == 0, "Accuracy not reached")
450 : :
451 : 65934 : K0cos_dy=quad
452 : :
453 : 65934 : end function K0cos_dy
454 : : !!***
455 : :
456 : :
457 : :
458 : :
459 : : !----------------------------------------------------------------------
460 : :
461 : : real(dp) function K0cos_dy_r0(xx)
462 : :
463 : : real(dp),intent(in) :: xx
464 : :
465 : : !Local variables-------------------------------
466 : : !scalars
467 : : integer :: ierr
468 : : real(dp) :: quad,yx
469 : : !************************************************************************
470 : :
471 : : ! $ K0cos_dy_r0(x)= \int_{-b/2}^{-y(x)} K0(|qpg_z|\rho) cos(x.qpg_x+y.qpg_y)dy
472 : : ! +\int_{y(x)}^{b/2} K0(|qpg_z|\rho)cos(x.qpg_x+y.qpg_y)dy$
473 : : ! where y(x)=SQRT(r0^2-x^2) and x<=r0
474 : : !
475 : : xx_=xx; yx=SQRT(r0_**2-xx**2)
476 : : call quadrature(K0cos,-hb_,-yx,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
477 : : ABI_CHECK(ierr == 0, "Accuracy not reached in quadrature")
478 : : K0cos_dy_r0=quad
479 : :
480 : : call quadrature(K0cos,+yx,+hb_,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
481 : : ABI_CHECK(ierr == 0, "Accuracy not reached in quadrature")
482 : :
483 : : K0cos_dy_r0=quad+K0cos_dy_r0
484 : :
485 : : end function K0cos_dy_r0
486 : : !!***
487 : :
488 : : !----------------------------------------------------------------------
489 : :
490 : : real(dp) function K0cos_dth_r0(rho)
491 : :
492 : : real(dp),intent(in) :: rho
493 : :
494 : : !Local variables-------------------------------
495 : : !scalars
496 : : integer :: ierr
497 : : real(dp) :: quad,arg,k0,tmp
498 : :
499 : : !************************************************************************
500 : :
501 : : ! $ K0cos_dth_r0(\rho)=
502 : : ! \int_{0}^{2pi)} K0(|qpg_z|\rho)cos(\rho.cos(\theta).qpg_x+\rho.sin(\theta).qpg_y) d\theta $
503 : : !
504 : : ! where y(x)=SQRT(r0^2-x^2) and x<=r0
505 : : !
506 : : rho_=rho
507 : : call quadrature(Fcos_th,zero,two_pi,qopt_,quad,ierr,ntrial_,accuracy_,npts_)
508 : : ABI_CHECK(ierr == 0, "Accuracy not reached in quadrature")
509 : :
510 : : arg=qpg_para_*rho_
511 : : tmp=zero
512 : : if (arg>tol6) then
513 : : call CALCK0(arg,k0,1)
514 : : tmp=k0*rho_
515 : : end if
516 : : K0cos_dth_r0=quad*tmp
517 : :
518 : : end function K0cos_dth_r0
519 : : !!***
520 : :
521 : : !----------------------------------------------------------------------
522 : :
523 : : pure real(dp) function Fcos_th(theta)
524 : :
525 : : real(dp),intent(in) :: theta
526 : :
527 : : !************************************************************************
528 : :
529 : : ! $ Fcos_th(\theta)=rho*K0(\rho*|qpg_z|)*COS(\rho.COS(\theta).qpg_x+\rho.SIN/(\theta)*qpg_y) $
530 : :
531 : : !arg=qpg_para_*rho_
532 : : !call CALCK0(arg,k0,1)
533 : : !tmp=k0*rho_
534 : : Fcos_th=COS(rho_*COS(theta)*qpgx_+rho_*SIN(theta)*qpgy_)
535 : :
536 : : end function Fcos_th
537 : : !!***
538 : :
539 : : !----------------------------------------------------------------------
540 : :
541 : : !the following functions should be used to deal with the singularity in the Cylindrical cutoff
542 : : !TODO Not yet used and indeed are still private
543 : :
544 : : function K0fit(mq,nn) result(vals)
545 : :
546 : : integer,intent(in) :: nn
547 : : real(dp),intent(in) :: mq
548 : : real(dp) :: vals(nn)
549 : :
550 : : !Local variables-------------------------------
551 : : !scalars
552 : : integer :: ii
553 : : real(dp) :: mqh
554 : : !arrays
555 : : real(dp),parameter :: cc(7)=(/-0.57721566,0.42278420,0.23069756, &
556 : : 0.03488590,0.00262698,0.00010750,0.00000740/)
557 : : ! *************************************************************************
558 : :
559 : : if (nn>8.or.nn<1) then
560 : : ABI_ERROR("nn>8.or.nn<1 not implemented")
561 : : end if
562 : :
563 : : ! === Eq 9.8.5 in Abramovitz ===
564 : : vals(1)=-LOG(mq*half)*I0(mq)
565 : : mqh=mq*half
566 : : do ii=2,nn
567 : : vals(ii)=cc(ii-1)*mqh**(2*(ii-2))
568 : : end do
569 : :
570 : : end function K0fit
571 : :
572 : : real(dp) function K0fit_int(mq,par,nn) result(integ)
573 : :
574 : : integer,intent(in) :: nn
575 : : real(dp),intent(in) :: mq
576 : : real(dp),intent(in) :: par(nn)
577 : :
578 : : !Local variables-------------------------------
579 : : !scalars
580 : : integer :: ii,aa
581 : : real(dp) :: mqh
582 : : !arrays
583 : : real(dp),parameter :: cc(7)=(/-0.57721566,0.42278420,0.23069756,&
584 : : & 0.03488590,0.00262698,0.00010750,0.00000740/)
585 : : ! *************************************************************************
586 : :
587 : : if (nn>8.or.nn<1) then
588 : : ABI_ERROR("nn>8.or.nn<1 not implemented")
589 : : end if
590 : :
591 : : mqh=mq*half
592 : : integ=-par(1)*int_I0ln(mqh)
593 : : ! primitive of polynomial \sum_0^{N/2} cc_{2i} (x/2)^{2*i}
594 : : do ii=2,nn
595 : : aa=(2*(ii-1)+1)
596 : : integ=integ+par(ii)*two*cc(ii-1)*(mqh**aa)/aa
597 : : end do
598 : :
599 : : end function K0fit_int
600 : :
601 : : real(dp) function I0(xx)
602 : :
603 : : real(dp),intent(in) :: xx
604 : :
605 : : !Local variables-------------------------------
606 : : real(dp) :: tt
607 : :
608 : : ! *************************************************************************
609 : :
610 : : ! Eq 9.8.1 of Abramovitz, entering the expansion of K0 -->0
611 : : ! Expansion holds for |x|<3.75, Error<1.6*10D-07
612 : : tt=xx/3.75
613 : : I0=one+3.5156229*tt**2+3.0899424*tt**4 +1.2067492*tt**6 &
614 : : +0.2659732*tt**8+0.0360768*tt**10+0.0045813*tt**12
615 : : end function I0
616 : :
617 : : ! Primitive of x^m Ln(x) for m/=-1
618 : : real(dp) function int_xmln(xx,mm) result(res)
619 : :
620 : : integer,intent(in) :: mm
621 : : real(dp),intent(in) :: xx
622 : :
623 : : ! *********************************************************************
624 : :
625 : : if (mm==-1) then
626 : : ABI_BUG('invalid value for mm')
627 : : end if
628 : :
629 : : if (xx<=zero) then
630 : : ABI_BUG(' invalid value for xx')
631 : : end if
632 : :
633 : : res= (xx**(mm+1))/(mm+1) * (LOG(xx) - one/(mm+1))
634 : :
635 : : end function int_xmln
636 : :
637 : : ! Primitive function of ln(x/2)*I0(x) = sum_0^{N/2} 2^{2s+1} c_{2s} T(x/2,2s)
638 : : ! where T(x,s)=\int x^s ln(x)dx
639 : : real(dp) function int_I0ln(xx) result(res)
640 : :
641 : : !Arguments ------------------------------------
642 : : real(dp),intent(in) :: xx
643 : :
644 : : !Local variables-------------------------------
645 : : real(dp) :: yy
646 : : ! *********************************************************************
647 : :
648 : : yy=xx*half
649 : : res = ( one*2 *int_xmln(yy,0) &
650 : : & +3.5156229*2**3 *int_xmln(yy,2) &
651 : : & +3.0899424*2**5 *int_xmln(yy,4) &
652 : : & +1.2067492*2**7 *int_xmln(yy,6) &
653 : : & +0.2659732*2**9 *int_xmln(yy,8) &
654 : : & +0.0360768*2**11*int_xmln(yy,10) &
655 : : & +0.0045813*2**13*int_xmln(yy,12) &
656 : : & )
657 : :
658 : : end function int_I0ln
659 : : !!***
660 : :
661 : : end module m_cutoff_cylinder
662 : : !!***
|