45 double complex,
allocatable :: flm(:,:),Alm(:,:),Blm(:,:)
46 double precision,
allocatable :: Rlm(:,:), xrg(:)
47 double precision,
public ::
r_s=2.5d0,
r_0=1.d0
48 integer,
allocatable :: lmaxarray(:)
50 logical,
public ::
trunc=.false.
64 double precision,
allocatable :: b_r0(:,:)
65 double precision,
allocatable :: theta(:),phi(:),cfwm(:)
66 double precision :: rsl,xrl,dxr
67 integer :: xm,ym,
l,m,amode,file_handle,il,ir,nlarr,nsh
68 integer,
dimension(MPI_STATUS_SIZE) :: statuss
70 character(len=*) :: mapname
71 character(len=80) :: fharmcoef
73 fharmcoef=mapname//
'.coef'
74 inquire(file=fharmcoef, exist=aexist)
76 if(
mype==0)
write(*,
'(2a)') &
77 'Using existing PFSS coefficient file; pfss_theta_quadrature is ignored: ',&
80 call mpi_file_open(mpi_comm_self,fharmcoef,mpi_mode_rdonly, &
81 mpi_info_null,file_handle,
ierrmpi)
82 call mpi_file_read(file_handle,
lmax,1,mpi_integer,statuss,
ierrmpi)
84 call mpi_file_read(file_handle,flm,(
lmax+1)*(
lmax+1),&
85 mpi_double_complex,statuss,
ierrmpi)
86 call mpi_file_close(file_handle,
ierrmpi)
96 inquire(file=mapname,exist=aexist)
98 if(
mype==0)
write(*,
'(2a)')
"can not find file:",mapname
99 call mpistop(
"no input magnetogram found")
101 call mpi_file_open(mpi_comm_self,mapname,mpi_mode_rdonly,mpi_info_null,&
103 call mpi_file_read(file_handle,xm,1,mpi_integer,statuss,
ierrmpi)
104 call mpi_file_read(file_handle,ym,1,mpi_integer,statuss,
ierrmpi)
107 allocate(b_r0(xm,ym))
110 call mpi_file_read(file_handle,theta,ym,mpi_double_precision,&
112 call mpi_file_read(file_handle,phi,xm,mpi_double_precision,&
114 call mpi_file_read(file_handle,b_r0,xm*ym,mpi_double_precision,&
116 call mpi_file_close(file_handle,
ierrmpi)
117 print*,
'nphi,ntheta',xm,ym
118 print*,
'theta range:',minval(theta),maxval(theta)
119 print*,
'phi range:',minval(phi),maxval(phi)
120 print*,
'Brmax,Brmin',maxval(b_r0),minval(b_r0)
124 call cfweights_cell_area(ym,theta,cfwm)
125 case(
'gauss_legendre')
126 call cfweights_gauss_legendre(ym,dcos(theta),cfwm)
128 call mpistop(
"Unknown pfss_theta_quadrature")
131 call coef(b_r0,xm,ym,dcos(theta),dsin(theta),cfwm)
135 amode=ior(mpi_mode_create,mpi_mode_wronly)
136 call mpi_file_open(mpi_comm_self,fharmcoef,amode, &
137 mpi_info_null,file_handle,
ierrmpi)
138 call mpi_file_write(file_handle,
lmax,1,mpi_integer,statuss,
ierrmpi)
139 call mpi_file_write(file_handle,flm,(
lmax+1)*(
lmax+1),&
140 mpi_double_complex,statuss,
ierrmpi)
141 call mpi_file_close(file_handle,
ierrmpi)
147 if(
npe>1)
call mpi_bcast(flm,(
lmax+1)*(
lmax+1),mpi_double_complex,0,&
152 allocate(lmaxarray(nlarr))
156 dxr=(
r_s-
r_0)/dble(nlarr-1)
158 xrg(ir)=dxr*dble(ir-1)+
r_0
177 rlm(
l,m)=dsqrt(dble(
l**2-m**2)/dble(4*
l**2-1))
178 blm(
l,m)=-flm(
l,m)/(1.d0+dble(
l)+dble(
l)*rsl)
179 alm(
l,m)=-rsl*blm(
l,m)
185 subroutine cfweights_cell_area(ym,theta,cfwm)
188 integer,
intent(in) :: ym
189 double precision,
intent(in) :: theta(ym)
190 double precision,
intent(out) :: cfwm(ym)
192 double precision,
dimension(ym) :: miu
193 double precision :: edge_l,edge_r
197 if(miu(1)<=miu(ym))
then
202 edge_l=0.5d0*(miu(i-1)+miu(i))
207 edge_r=0.5d0*(miu(i)+miu(i+1))
209 cfwm(i)=dabs(edge_r-edge_l)*(2.d0*dpi)
216 edge_l=0.5d0*(miu(i-1)+miu(i))
221 edge_r=0.5d0*(miu(i)+miu(i+1))
223 cfwm(i)=dabs(edge_r-edge_l)*(2.d0*dpi)
227 end subroutine cfweights_cell_area
229 subroutine cfweights_gauss_legendre(ym,miu,cfwm)
232 integer,
intent(in) :: ym
233 double precision,
intent(in) :: miu(ym)
234 double precision,
intent(out) :: cfwm(ym)
236 double precision,
dimension(ym) :: pl,pm2,pm1,pprime,sintheta
237 double precision :: lr
240 sintheta=dsqrt(1.d0-miu**2)
247 pl=(2.d0-lr)*pm1*miu-(1.d0-lr)*pm2
252 pprime=(dble(ym)*pl)/sintheta**2
253 cfwm=2.d0/(sintheta*pprime)**2
256 end subroutine cfweights_gauss_legendre
258 subroutine coef(b_r0,xm,ym,miu,mius,cfwm)
261 integer,
intent(in) :: xm,ym
262 double precision,
intent(in) :: b_r0(xm,ym),cfwm(ym),miu(ym),mius(ym)
264 double complex :: bm(0:xm-1,0:ym-1)
265 double precision,
dimension(xm) :: fftmr,fftmi
266 double precision,
dimension(0:lmax) :: n_mm
267 double precision,
dimension(ym) :: p_lm1,p_lm2,old_pmm,p_l
268 double precision :: mr,lr,c1,c2
269 integer ::
l,m,i,j,stat
273 fftmr=b_r0(:,i)/dble(xm)
275 call fft_raw(fftmr,fftmi,xm,xm,xm,-1)
276 bm(:,i-1)=(fftmr+(0.d0,1.d0)*fftmi)
278 n_mm(0)=1.d0/dsqrt(4.d0*dpi)
280 n_mm(m)=-n_mm(m-1)*dsqrt(1.d0+1.d0/dble(2*m))
284 p_lm1=p_lm2*miu*dsqrt(3.d0)
286 flm(0,0)=sum(bm(0,:)*p_lm2*cfwm)
288 flm(1,0)=sum(bm(0,:)*p_lm1*cfwm)
291 c1=dsqrt(4.d0-1.d0/lr**2)
292 c2=-(1.d0-1.d0/lr)*dsqrt((2.d0*lr+1.d0)/(2.d0*lr-3.d0))
293 p_l=c1*miu*p_lm1+c2*p_lm2
295 flm(
l,0)=sum(bm(0,:)*p_l*cfwm)
306 p_lm2=old_pmm*mius*n_mm(m)/n_mm(m-1)
307 p_lm1=p_lm2*miu*dsqrt(dble(2*m+3))
311 flm(m,m)=sum(bm(m,:)*p_lm2*cfwm)
313 if(m<
lmax) flm(m+1,m)=sum(bm(m,:)*p_lm1*cfwm)
317 c1=dsqrt((4.d0*lr**2-1.d0)/(lr**2-mr**2))
318 c2=-dsqrt(((2.d0*lr+1.d0)*((lr-1.d0)**2-mr**2))/((2.d0*lr-3.d0)*(lr**2-&
320 p_l=c1*miu*p_lm1+c2*p_lm2
321 flm(
l,m)=sum(bm(m,:)*p_l*cfwm)
329 subroutine pfss(ixI^L,ixO^L,Bpf,x)
332 integer,
intent(in) :: ixi^
l,ixo^
l
333 double precision,
intent(in) :: x(ixi^s,1:
ndim)
334 double precision,
intent(out) :: bpf(ixi^s,1:
ndir)
336 double complex :: bt(0:
lmax,0:
lmax,ixomin1:ixomax1)
337 double precision :: phase(ixi^s,1:
ndir),bpfiv(ixomin3:ixomax3,ixomin2:ixomax2)
338 double precision :: miu(ixomin2:ixomax2),mius(ixomin2:ixomax2),xr
339 double precision :: tmp(ixomin2:ixomax2)
340 integer ::
l,m,ix^
d,j,l1,l2,ntheta,nphi,ir,qlmax
343 nphi=ixomax3-ixomin3+1
344 ntheta=ixomax2-ixomin2+1
345 tmp(ixomin2:ixomax2)=x(ixomin1,ixomax2:ixomin2:-1,ixomin3,2)
346 miu(ixomin2:ixomax2)=dcos(tmp(ixomin2:ixomax2))
347 mius(ixomin2:ixomax2)=dsin(tmp(ixomin2:ixomax2))
348 do ix1=ixomin1,ixomax1
349 xr=x(ix1,ixomin2,ixomin3,1)
351 do ir=1,
size(lmaxarray)
354 if(ir>
size(lmaxarray)) ir=
size(lmaxarray)
362 bt(
l,m,ix1)=alm(
l,m)*dble(
l)*xr**(
l-1)-blm(
l,m)*dble(
l+1)*xr**(-
l-2)
365 call inv_sph_transform(bt(:,:,ix1),x(ixomin1,ixomin2,&
366 ixomin3:ixomax3,3),miu,mius,nphi,ntheta,bpfiv,qlmax)
367 do ix3=ixomin3,ixomax3
368 do ix2=ixomin2,ixomax2
369 bpf(ix1,ix2,ix3,1)=bpfiv(ix3,ixomax2-ix2+ixomin2)
376 bt(
l,m,ix1)=-rlm(
l+1,m)*dble(
l+2)*&
377 (alm(
l+1,m)*xr**
l+blm(
l+1,m)*xr**(-
l-3))
378 else if (
l>=1 .and.
l<=
lmax-1)
then
379 bt(
l,m,ix1)=rlm(
l,m)*&
380 dble(
l-1)*(alm(
l-1,m)*xr**(
l-2)+blm(
l-1,m)*&
381 xr**(-
l-1))-rlm(
l+1,m)*dble(
l+2)*&
382 (alm(
l+1,m)*xr**
l+blm(
l+1,m)*xr**(-
l-3))
384 bt(
l,m,ix1)=rlm(
l,m)*&
385 dble(
l-1)*(alm(
l-1,m)*xr**(
l-2)+blm(
l-1,m)*xr**(-
l-1))
389 call inv_sph_transform(bt(:,:,ix1),x(ixomin1,ixomin2,&
390 ixomin3:ixomax3,3),miu,mius,nphi,ntheta,bpfiv,qlmax)
391 do ix3=ixomin3,ixomax3
392 do ix2=ixomin2,ixomax2
393 bpf(ix1,ix2,ix3,2)=bpfiv(ix3,ixomax2-ix2+ixomin2)/mius(&
401 bt(
l,m,ix1)=(0.d0,1.d0)*m*(alm(
l,m)*xr**(
l-1)+blm(
l,m)*xr**(-
l-2))
404 call inv_sph_transform(bt(:,:,ix1),x(ixomin1,ixomin2,&
405 ixomin3:ixomax3,3),miu,mius,nphi,ntheta,bpfiv,qlmax)
406 do ix3=ixomin3,ixomax3
407 do ix2=ixomin2,ixomax2
408 bpf(ix1,ix2,ix3,3)=bpfiv(ix3,ixomax2-ix2+ixomin2)/mius(&
425 subroutine inv_sph_transform(Bt,phi,miu,mius,nphi,ntheta,Bpf,qlmax)
428 integer,
intent(in) :: nphi,ntheta,qlmax
429 double complex,
intent(in) :: bt(0:
lmax,0:
lmax)
430 double precision,
intent(in) :: phi(nphi),miu(ntheta),mius(ntheta)
431 double precision,
intent(out) :: bpf(nphi,ntheta)
433 double precision,
dimension(0:lmax,0:lmax) :: cp,phase,bamp
434 double precision,
dimension(ntheta) :: cp_1_0,cp_l_0,cp_lm1_0,cp_lm2_0,cp_m_m
435 double precision,
dimension(ntheta) :: cp_1_m,cp_l_m,cp_lm1_m,cp_lm2_m,cp_mp1_m
436 double precision :: angpart(nphi)
437 double precision :: ld,md,c1,c2,cp_0_0
438 integer ::
l,m,iph,ith
442 phase=atan2(dimag(bt),dble(bt))
446 cp_0_0=dsqrt(1.d0/(4.d0*dpi))
448 bpf=bpf+bamp(0,0)*dcos(phase(0,0))*cp_0_0
451 cp_1_0=dsqrt(3.d0)*miu*cp_0_0
453 bpf(iph,:)=bpf(iph,:)+bamp(1,0)*dcos(phase(1,0))*cp_1_0
463 c1=dsqrt(4.d0*ld**2-1.d0)/ld
464 c2=dsqrt((2.d0*ld+1.d0)/(2.d0*ld-3.d0))*(ld-1.d0)/ld
465 cp_l_0=c1*miu*cp_lm1_0-c2*cp_lm2_0
467 bpf(iph,:)=bpf(iph,:)+bamp(
l,0)*dcos(phase(
l,0))*cp_l_0
476 cp_m_m=-dsqrt(1.d0+1.d0/(2.d0*md))*mius*cp_m_m
478 angpart(iph)=dcos(md*phi(iph)+phase(m,m))
482 bpf(iph,ith)=bpf(iph,ith)+bamp(m,m)*angpart(iph)*cp_m_m(ith)
488 cp_mp1_m=dsqrt(2.d0*md+3.d0)*miu*cp_m_m
489 angpart=dcos(md*phi+phase(m+1,m))
492 bpf(iph,ith)=bpf(iph,ith)+bamp(m+1,m)*angpart(iph)*cp_mp1_m(ith)
505 c1=dsqrt((4.d0*ld**2-1.d0)/(ld**2-md**2))
506 c2=dsqrt((2.d0*ld+1.d0)*((ld-1.d0)**2-md**2)/(2.d0*ld-3.d0)/(ld**2-md**2))
507 cp_l_m=c1*miu*cp_lm1_m-c2*cp_lm2_m
508 angpart=dcos(md*phi+phase(
l,m))
511 bpf(iph,ith)=bpf(iph,ith)+bamp(
l,m)*angpart(iph)*cp_l_m(ith)
518 end subroutine inv_sph_transform
subroutine, public mpistop(message)
Exit MPI-AMRVAC with an error message.
Self-contained complex FFT utilities based on the mixed-radix Singleton transform historically embedd...
subroutine, public fft_raw(a, b, ntot, n, nspan, isn)
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