44 double complex,
allocatable :: flm(:,:),Alm(:,:),Blm(:,:)
45 double precision,
allocatable :: Rlm(:,:), xrg(:)
46 double precision,
public ::
r_s=2.5d0,
r_0=1.d0
47 integer,
allocatable :: lmaxarray(:)
49 logical,
public ::
trunc=.false.
63 double precision,
allocatable :: b_r0(:,:)
64 double precision,
allocatable :: theta(:),phi(:),cfwm(:)
65 double precision :: rsl,xrl,dxr
66 integer :: xm,ym,
l,m,amode,file_handle,il,ir,nlarr,nsh
67 integer,
dimension(MPI_STATUS_SIZE) :: statuss
69 character(len=*) :: mapname
70 character(len=80) :: fharmcoef
72 fharmcoef=mapname//
'.coef'
73 inquire(file=fharmcoef, exist=aexist)
75 if(
mype==0)
write(*,
'(2a)') &
76 'Using existing PFSS coefficient file; pfss_theta_quadrature is ignored: ',&
79 call mpi_file_open(mpi_comm_self,fharmcoef,mpi_mode_rdonly, &
80 mpi_info_null,file_handle,
ierrmpi)
81 call mpi_file_read(file_handle,
lmax,1,mpi_integer,statuss,
ierrmpi)
83 call mpi_file_read(file_handle,flm,(
lmax+1)*(
lmax+1),&
84 mpi_double_complex,statuss,
ierrmpi)
85 call mpi_file_close(file_handle,
ierrmpi)
95 inquire(file=mapname,exist=aexist)
97 if(
mype==0)
write(*,
'(2a)')
"can not find file:",mapname
98 call mpistop(
"no input magnetogram found")
100 call mpi_file_open(mpi_comm_self,mapname,mpi_mode_rdonly,mpi_info_null,&
102 call mpi_file_read(file_handle,xm,1,mpi_integer,statuss,
ierrmpi)
103 call mpi_file_read(file_handle,ym,1,mpi_integer,statuss,
ierrmpi)
106 allocate(b_r0(xm,ym))
109 call mpi_file_read(file_handle,theta,ym,mpi_double_precision,&
111 call mpi_file_read(file_handle,phi,xm,mpi_double_precision,&
113 call mpi_file_read(file_handle,b_r0,xm*ym,mpi_double_precision,&
115 call mpi_file_close(file_handle,
ierrmpi)
116 print*,
'nphi,ntheta',xm,ym
117 print*,
'theta range:',minval(theta),maxval(theta)
118 print*,
'phi range:',minval(phi),maxval(phi)
119 print*,
'Brmax,Brmin',maxval(b_r0),minval(b_r0)
123 call cfweights_cell_area(ym,theta,cfwm)
124 case(
'gauss_legendre')
125 call cfweights_gauss_legendre(ym,dcos(theta),cfwm)
127 call mpistop(
"Unknown pfss_theta_quadrature")
130 call coef(b_r0,xm,ym,dcos(theta),dsin(theta),cfwm)
134 amode=ior(mpi_mode_create,mpi_mode_wronly)
135 call mpi_file_open(mpi_comm_self,fharmcoef,amode, &
136 mpi_info_null,file_handle,
ierrmpi)
137 call mpi_file_write(file_handle,
lmax,1,mpi_integer,statuss,
ierrmpi)
138 call mpi_file_write(file_handle,flm,(
lmax+1)*(
lmax+1),&
139 mpi_double_complex,statuss,
ierrmpi)
140 call mpi_file_close(file_handle,
ierrmpi)
146 if(
npe>1)
call mpi_bcast(flm,(
lmax+1)*(
lmax+1),mpi_double_complex,0,&
151 allocate(lmaxarray(nlarr))
155 dxr=(
r_s-
r_0)/dble(nlarr-1)
157 xrg(ir)=dxr*dble(ir-1)+
r_0
176 rlm(
l,m)=dsqrt(dble(
l**2-m**2)/dble(4*
l**2-1))
177 blm(
l,m)=-flm(
l,m)/(1.d0+dble(
l)+dble(
l)*rsl)
178 alm(
l,m)=-rsl*blm(
l,m)
184 subroutine cfweights_cell_area(ym,theta,cfwm)
187 integer,
intent(in) :: ym
188 double precision,
intent(in) :: theta(ym)
189 double precision,
intent(out) :: cfwm(ym)
191 double precision,
dimension(ym) :: miu
192 double precision :: edge_l,edge_r
196 if(miu(1)<=miu(ym))
then
201 edge_l=0.5d0*(miu(i-1)+miu(i))
206 edge_r=0.5d0*(miu(i)+miu(i+1))
208 cfwm(i)=dabs(edge_r-edge_l)*(2.d0*dpi)
215 edge_l=0.5d0*(miu(i-1)+miu(i))
220 edge_r=0.5d0*(miu(i)+miu(i+1))
222 cfwm(i)=dabs(edge_r-edge_l)*(2.d0*dpi)
226 end subroutine cfweights_cell_area
228 subroutine cfweights_gauss_legendre(ym,miu,cfwm)
231 integer,
intent(in) :: ym
232 double precision,
intent(in) :: miu(ym)
233 double precision,
intent(out) :: cfwm(ym)
235 double precision,
dimension(ym) :: pl,pm2,pm1,pprime,sintheta
236 double precision :: lr
239 sintheta=dsqrt(1.d0-miu**2)
246 pl=(2.d0-lr)*pm1*miu-(1.d0-lr)*pm2
251 pprime=(dble(ym)*pl)/sintheta**2
252 cfwm=2.d0/(sintheta*pprime)**2
255 end subroutine cfweights_gauss_legendre
257 subroutine coef(b_r0,xm,ym,miu,mius,cfwm)
260 integer,
intent(in) :: xm,ym
261 double precision,
intent(in) :: b_r0(xm,ym),cfwm(ym),miu(ym),mius(ym)
263 double complex :: bm(0:xm-1,0:ym-1)
264 double precision,
dimension(xm) :: fftmr,fftmi
265 double precision,
dimension(0:lmax) :: n_mm
266 double precision,
dimension(ym) :: p_lm1,p_lm2,old_pmm,p_l
267 double precision :: mr,lr,c1,c2
268 integer ::
l,m,i,j,stat
272 fftmr=b_r0(:,i)/dble(xm)
274 call fft(fftmr,fftmi,xm,xm,xm,-1)
275 bm(:,i-1)=(fftmr+(0.d0,1.d0)*fftmi)
277 n_mm(0)=1.d0/dsqrt(4.d0*dpi)
279 n_mm(m)=-n_mm(m-1)*dsqrt(1.d0+1.d0/dble(2*m))
283 p_lm1=p_lm2*miu*dsqrt(3.d0)
285 flm(0,0)=sum(bm(0,:)*p_lm2*cfwm)
287 flm(1,0)=sum(bm(0,:)*p_lm1*cfwm)
290 c1=dsqrt(4.d0-1.d0/lr**2)
291 c2=-(1.d0-1.d0/lr)*dsqrt((2.d0*lr+1.d0)/(2.d0*lr-3.d0))
292 p_l=c1*miu*p_lm1+c2*p_lm2
294 flm(
l,0)=sum(bm(0,:)*p_l*cfwm)
305 p_lm2=old_pmm*mius*n_mm(m)/n_mm(m-1)
306 p_lm1=p_lm2*miu*dsqrt(dble(2*m+3))
310 flm(m,m)=sum(bm(m,:)*p_lm2*cfwm)
312 if(m<
lmax) flm(m+1,m)=sum(bm(m,:)*p_lm1*cfwm)
316 c1=dsqrt((4.d0*lr**2-1.d0)/(lr**2-mr**2))
317 c2=-dsqrt(((2.d0*lr+1.d0)*((lr-1.d0)**2-mr**2))/((2.d0*lr-3.d0)*(lr**2-&
319 p_l=c1*miu*p_lm1+c2*p_lm2
320 flm(
l,m)=sum(bm(m,:)*p_l*cfwm)
328 subroutine pfss(ixI^L,ixO^L,Bpf,x)
331 integer,
intent(in) :: ixi^
l,ixo^
l
332 double precision,
intent(in) :: x(ixi^s,1:
ndim)
333 double precision,
intent(out) :: bpf(ixi^s,1:
ndir)
335 double complex :: bt(0:
lmax,0:
lmax,ixomin1:ixomax1)
336 double precision :: phase(ixi^s,1:
ndir),bpfiv(ixomin3:ixomax3,ixomin2:ixomax2)
337 double precision :: miu(ixomin2:ixomax2),mius(ixomin2:ixomax2),xr
338 double precision :: tmp(ixomin2:ixomax2)
339 integer ::
l,m,ix^
d,j,l1,l2,ntheta,nphi,ir,qlmax
342 nphi=ixomax3-ixomin3+1
343 ntheta=ixomax2-ixomin2+1
344 tmp(ixomin2:ixomax2)=x(ixomin1,ixomax2:ixomin2:-1,ixomin3,2)
345 miu(ixomin2:ixomax2)=dcos(tmp(ixomin2:ixomax2))
346 mius(ixomin2:ixomax2)=dsin(tmp(ixomin2:ixomax2))
347 do ix1=ixomin1,ixomax1
348 xr=x(ix1,ixomin2,ixomin3,1)
350 do ir=1,
size(lmaxarray)
353 if(ir>
size(lmaxarray)) ir=
size(lmaxarray)
361 bt(
l,m,ix1)=alm(
l,m)*dble(
l)*xr**(
l-1)-blm(
l,m)*dble(
l+1)*xr**(-
l-2)
364 call inv_sph_transform(bt(:,:,ix1),x(ixomin1,ixomin2,&
365 ixomin3:ixomax3,3),miu,mius,nphi,ntheta,bpfiv,qlmax)
366 do ix3=ixomin3,ixomax3
367 do ix2=ixomin2,ixomax2
368 bpf(ix1,ix2,ix3,1)=bpfiv(ix3,ixomax2-ix2+ixomin2)
375 bt(
l,m,ix1)=-rlm(
l+1,m)*dble(
l+2)*&
376 (alm(
l+1,m)*xr**
l+blm(
l+1,m)*xr**(-
l-3))
377 else if (
l>=1 .and.
l<=
lmax-1)
then
378 bt(
l,m,ix1)=rlm(
l,m)*&
379 dble(
l-1)*(alm(
l-1,m)*xr**(
l-2)+blm(
l-1,m)*&
380 xr**(-
l-1))-rlm(
l+1,m)*dble(
l+2)*&
381 (alm(
l+1,m)*xr**
l+blm(
l+1,m)*xr**(-
l-3))
383 bt(
l,m,ix1)=rlm(
l,m)*&
384 dble(
l-1)*(alm(
l-1,m)*xr**(
l-2)+blm(
l-1,m)*xr**(-
l-1))
388 call inv_sph_transform(bt(:,:,ix1),x(ixomin1,ixomin2,&
389 ixomin3:ixomax3,3),miu,mius,nphi,ntheta,bpfiv,qlmax)
390 do ix3=ixomin3,ixomax3
391 do ix2=ixomin2,ixomax2
392 bpf(ix1,ix2,ix3,2)=bpfiv(ix3,ixomax2-ix2+ixomin2)/mius(&
400 bt(
l,m,ix1)=(0.d0,1.d0)*m*(alm(
l,m)*xr**(
l-1)+blm(
l,m)*xr**(-
l-2))
403 call inv_sph_transform(bt(:,:,ix1),x(ixomin1,ixomin2,&
404 ixomin3:ixomax3,3),miu,mius,nphi,ntheta,bpfiv,qlmax)
405 do ix3=ixomin3,ixomax3
406 do ix2=ixomin2,ixomax2
407 bpf(ix1,ix2,ix3,3)=bpfiv(ix3,ixomax2-ix2+ixomin2)/mius(&
424 subroutine inv_sph_transform(Bt,phi,miu,mius,nphi,ntheta,Bpf,qlmax)
427 integer,
intent(in) :: nphi,ntheta,qlmax
428 double complex,
intent(in) :: bt(0:
lmax,0:
lmax)
429 double precision,
intent(in) :: phi(nphi),miu(ntheta),mius(ntheta)
430 double precision,
intent(out) :: bpf(nphi,ntheta)
432 double precision,
dimension(0:lmax,0:lmax) :: cp,phase,bamp
433 double precision,
dimension(ntheta) :: cp_1_0,cp_l_0,cp_lm1_0,cp_lm2_0,cp_m_m
434 double precision,
dimension(ntheta) :: cp_1_m,cp_l_m,cp_lm1_m,cp_lm2_m,cp_mp1_m
435 double precision :: angpart(nphi)
436 double precision :: ld,md,c1,c2,cp_0_0
437 integer ::
l,m,iph,ith
441 phase=atan2(dimag(bt),dble(bt))
445 cp_0_0=dsqrt(1.d0/(4.d0*dpi))
447 bpf=bpf+bamp(0,0)*dcos(phase(0,0))*cp_0_0
450 cp_1_0=dsqrt(3.d0)*miu*cp_0_0
452 bpf(iph,:)=bpf(iph,:)+bamp(1,0)*dcos(phase(1,0))*cp_1_0
462 c1=dsqrt(4.d0*ld**2-1.d0)/ld
463 c2=dsqrt((2.d0*ld+1.d0)/(2.d0*ld-3.d0))*(ld-1.d0)/ld
464 cp_l_0=c1*miu*cp_lm1_0-c2*cp_lm2_0
466 bpf(iph,:)=bpf(iph,:)+bamp(
l,0)*dcos(phase(
l,0))*cp_l_0
475 cp_m_m=-dsqrt(1.d0+1.d0/(2.d0*md))*mius*cp_m_m
477 angpart(iph)=dcos(md*phi(iph)+phase(m,m))
481 bpf(iph,ith)=bpf(iph,ith)+bamp(m,m)*angpart(iph)*cp_m_m(ith)
487 cp_mp1_m=dsqrt(2.d0*md+3.d0)*miu*cp_m_m
488 angpart=dcos(md*phi+phase(m+1,m))
491 bpf(iph,ith)=bpf(iph,ith)+bamp(m+1,m)*angpart(iph)*cp_mp1_m(ith)
504 c1=dsqrt((4.d0*ld**2-1.d0)/(ld**2-md**2))
505 c2=dsqrt((2.d0*ld+1.d0)*((ld-1.d0)**2-md**2)/(2.d0*ld-3.d0)/(ld**2-md**2))
506 cp_l_m=c1*miu*cp_lm1_m-c2*cp_lm2_m
507 angpart=dcos(md*phi+phase(
l,m))
510 bpf(iph,ith)=bpf(iph,ith)+bamp(
l,m)*angpart(iph)*cp_l_m(ith)
517 end subroutine inv_sph_transform
519 subroutine fft(a,b,ntot,n,nspan,isn)
563 double precision :: a(:),b(:)
567 dimension nfac(11),np(209)
569 dimension at(23),ck(23),bt(23),sk(23)
570 double precision :: c72,s72,s120,rad,radf,sd,cd,ak,bk,c1
571 double precision :: s1,aj,bj,akp,ajp,ajm,akm,bkp,bkm,bjp,bjm,aa
572 double precision :: bb,sk,ck,at,bt,s3,c3,s2,c2
573 integer :: i,ii,maxp,maxf,n,inc,isn,nt,ntot,ks,nspan,kspan,nn,jc,jf,m
574 integer :: k,j,jj,nfac,kt,np,kk,k1,k2,k3,k4,kspnn
588 c72=0.30901699437494742d0
589 s72=0.95105651629515357d0
590 s120=0.86602540378443865d0
591 rad=6.2831853071796d0
592 if(isn .ge. 0)
go to 10
602 radf=rad*dble(jc)*0.5d0
612 20
if(k-(k/16)*16 .eq. 0)
go to 15
619 30
if(mod(k,jj) .eq. 0)
go to 25
622 if(jj .le. k)
go to 30
623 if(k .gt. 4)
go to 40
628 40
if(k-(k/4)*4 .ne. 0)
go to 50
634 60
if(mod(k,j) .ne. 0)
go to 70
639 if(j .le. k)
go to 60
640 80
if(kt .eq. 0)
go to 100
645 if(j .ne. 0)
go to 90
647 100 sd=radf/dble(kspan)
652 if(nfac(i) .ne. 2)
go to 400
664 if(kk .le. nn)
go to 210
666 if(kk .le. jc)
go to 210
667 if(kk .gt. kspan)
go to 800
678 if(kk .lt. nt)
go to 230
682 if(kk .gt. k2)
go to 230
685 c1=2.d0-(ak**2+s1**2)
689 if(kk .lt. k2)
go to 230
692 if(kk .le. jc+jc)
go to 220
705 aj=(a(k1)-a(k2))*s120
706 bj=(b(k1)-b(k2))*s120
712 if(kk .lt. nn)
go to 320
714 if(kk .le. kspan)
go to 320
717 400
if(nfac(i) .ne. 4)
go to 600
737 if(isn .lt. 0)
go to 450
742 if(s1 .eq. 0.d0)
go to 460
743 430 a(k1)=akp*c1-bkp*s1
750 if(kk .le. nt)
go to 420
751 440 c2=c1-(cd*c1+sd*s1)
753 c1=2.d0-(c2**2+s1**2)
761 if(kk .le. kspan)
go to 420
763 if(kk .le. jc)
go to 410
764 if(kspan .eq. jc)
go to 800
770 if(s1 .ne. 0)
go to 430
778 if(kk .le. nt)
go to 420
816 if(kk .lt. nn)
go to 520
818 if(kk .le. kspan)
go to 520
824 if(k .eq. 3)
go to 320
825 if(k .eq. 5)
go to 510
826 if(k .eq. jf)
go to 640
831 if(jf .gt. maxf)
go to 998
835 630 ck(j)=ck(k)*c1+sk(k)*s1
836 sk(j)=ck(k)*s1-sk(k)*c1
841 if(j .lt. k)
go to 630
860 if(k1 .lt. k2)
go to 650
881 if(jj .gt. jf) jj=jj-jf
882 if(k .lt. jf)
go to 670
889 if(j .lt. k)
go to 660
891 if(kk .le. nn)
go to 640
893 if(kk .le. kspan)
go to 640
895 700
if(i .eq. m)
go to 800
906 if(kk .le. nt)
go to 730
911 if(kk .le. kspnn)
go to 730
914 c1=2.d0-(c2**2+s1**2)
918 if(kk .le. kspan)
go to 720
920 if(kk .le. jc+jc)
go to 710
925 if(kt .eq. 0)
go to 890
930 810 np(j+1)=np(j)/nfac(j)
931 np(k)=np(k+1)*nfac(j)
934 if(j .lt. k)
go to 810
940 if(n .ne. ntot)
go to 850
950 if(k2 .lt. ks)
go to 820
954 if(k2 .gt. np(j))
go to 830
956 840
if(kk .lt. k2)
go to 820
959 if(k2 .lt. ks)
go to 840
960 if(kk .lt. ks)
go to 830
973 if(kk .lt. k)
go to 860
976 if(kk .lt. nt)
go to 850
979 if(k2 .lt. ks)
go to 850
983 if(k2 .gt. np(j))
go to 870
985 880
if(kk .lt. k2)
go to 850
988 if(k2 .lt. ks)
go to 880
989 if(kk .lt. ks)
go to 870
991 890
if(2*kt+1 .ge. m)
return
996 900 nfac(j)=nfac(j)*nfac(j+1)
998 if(j .ne. kt)
go to 900
1001 if(nn .gt. maxp)
go to 998
1010 if(jj .ge. k2)
go to 902
1016 if(j .le. nn)
go to 904
1023 if(kk .ne. j)
go to 910
1027 if(kk .lt. 0)
go to 914
1028 if(kk .ne. j)
go to 910
1030 if(j .ne. nn)
go to 914
1035 if(np(j) .lt. 0)
go to 924
1038 if(jj .gt. maxf) kspan=maxf
1048 if(k1 .ne. kk)
go to 928
1056 if(k1 .ne. kk)
go to 936
1058 if(k .ne. j)
go to 932
1065 if(k1 .ne. kk)
go to 940
1066 if(jj .ne. 0)
go to 926
1067 if(j .ne. 1)
go to 924
1071 if(nt .ge. 0)
go to 924
1077 999
format(44h0array bounds exceeded within
subroutine fft)
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer, parameter ndim
Number of spatial dimensions for grid variables.
integer icomm
The MPI communicator.
integer mype
The rank of the current MPI task.
integer ndir
Number of spatial dimensions (components) for vector variables.
integer ierrmpi
A global MPI error return code.
double precision, dimension(:), allocatable, parameter d
integer npe
The number of MPI tasks.
module mod_pfss.t – potential field source surface model PURPOSE : to extrapolate global potential ma...
character(len=20), public pfss_theta_quadrature
double precision, public r_0
subroutine, public pfss(ixil, ixol, bpf, x)
subroutine, public harm_coef(mapname)
double precision, public r_s