MPI-AMRVAC 3.2
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_pfss.t
Go to the documentation of this file.
1!> module mod_pfss.t -- potential field source surface model
2!> PURPOSE : to extrapolate global potential magnetic field of the sun from
3!> synoptic magnetograms
4!> 2013.11.04 Developed by S. Moschou and C. Xia
5!> 2014.04.01 Allow to change source surface (C. Xia)
6!> PRECONDITIONS:
7!> 1. 3D spherical coordinates
8!> 2. A synoptic magnetogram in a binary file contains nphi, ntheta,
9!> theta(ntheta), phi(nphi), B_r(nphi,ntheta) succesively.
10!> 3. nphi, ntheta are long integers and other arrays are double precision.
11!> theta contains decreasing radians with increasing indice (Pi to 0)
12!> phi contains increasing radians with increasing indice (0 to 2*Pi)
13!> 4. By default, theta points are interpreted as cell centers and harmonic
14!> coefficients use cell-area quadrature in mu=cos(theta). To reproduce the
15!> old Gauss-Legendre quadrature, set
16!> pfss_theta_quadrature='gauss_legendre' before calling harm_coef.
17!> If a mapname.coef file already exists, it is reused and this setting does
18!> not take effect until that coefficient file is regenerated.
19!> USAGE:
20!> example for a magnetogram with name 'mdicr2020.dat':
21!>
22!> subroutine initglobaldata_usr
23!> ...
24!> R_0=1.d0 ! dimensionless Solar radius (default 1.0)
25!> R_s=2.5d0 ! dimensionless radius of source surface (default 2.5)
26!> lmax=120 ! use a fixed value instead of the value determined by the
27!> resolution of input magnetogram
28!> trunc=.true. ! use less spherical harmonics at larger distances
29!> call harm_coef('mdicr2020.dat')
30!> end subroutine initglobaldata_usr
31!>
32!> subroutine initonegrid_usr(ixI^L,ixO^L,w,x)
33!> ...
34!> double precision :: bpf(ixI^S,1:ndir)
35!> ...
36!> call pfss(ixI^L,ixO^L,bpf,x)
37!> w(ix^S,mag(:))=bpf(ix^S,:)
38!>
39!> end subroutine initonegrid_usr
41 implicit none
42 private
43
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(:)
48 integer, public :: lmax=0
49 logical, public :: trunc=.false.
50 character(len=20), public :: pfss_theta_quadrature='cell_area'
51
52 public :: harm_coef
53{^ifthreed
54 public :: pfss
55}
56
57contains
58
59 subroutine harm_coef(mapname)
61 use mod_comm_lib, only: mpistop
62
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
68 logical :: aexist
69 character(len=*) :: mapname
70 character(len=80) :: fharmcoef
71
72 fharmcoef=mapname//'.coef'
73 inquire(file=fharmcoef, exist=aexist)
74 if(aexist) then
75 if(mype==0) write(*,'(2a)') &
76 'Using existing PFSS coefficient file; pfss_theta_quadrature is ignored: ',&
77 trim(fharmcoef)
78 if(mype==0) then
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)
82 allocate(flm(0:lmax,0:lmax))
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)
86 end if
87 call mpi_barrier(icomm,ierrmpi)
88 if(npe>0) call mpi_bcast(lmax,1,mpi_integer,0,icomm,ierrmpi)
89 if(mype/=0) allocate(flm(0:lmax,0:lmax))
90 call mpi_barrier(icomm,ierrmpi)
91 if(npe>0) call mpi_bcast(flm,(lmax+1)*(lmax+1),mpi_double_complex,0,icomm,&
92 ierrmpi)
93 else
94 if(mype==0) then
95 inquire(file=mapname,exist=aexist)
96 if(.not. aexist) then
97 if(mype==0) write(*,'(2a)') "can not find file:",mapname
98 call mpistop("no input magnetogram found")
99 end if
100 call mpi_file_open(mpi_comm_self,mapname,mpi_mode_rdonly,mpi_info_null,&
101 file_handle,ierrmpi)
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)
104 if(lmax==0) lmax=min(2*ym/3,xm/3)
105
106 allocate(b_r0(xm,ym))
107 allocate(theta(ym))
108 allocate(phi(xm))
109 call mpi_file_read(file_handle,theta,ym,mpi_double_precision,&
110 statuss,ierrmpi)
111 call mpi_file_read(file_handle,phi,xm,mpi_double_precision,&
112 statuss,ierrmpi)
113 call mpi_file_read(file_handle,b_r0,xm*ym,mpi_double_precision,&
114 statuss,ierrmpi)
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)
120 allocate(cfwm(ym))
121 select case(trim(pfss_theta_quadrature))
122 case('cell_area')
123 call cfweights_cell_area(ym,theta,cfwm)
124 case('gauss_legendre')
125 call cfweights_gauss_legendre(ym,dcos(theta),cfwm)
126 case default
127 call mpistop("Unknown pfss_theta_quadrature")
128 end select
129 allocate(flm(0:lmax,0:lmax))
130 call coef(b_r0,xm,ym,dcos(theta),dsin(theta),cfwm)
131 deallocate(b_r0)
132 deallocate(theta)
133 deallocate(phi)
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)
141 endif
142 call mpi_barrier(icomm,ierrmpi)
143 if(npe>1) call mpi_bcast(lmax,1,mpi_integer,0,icomm,ierrmpi)
144 if(mype/=0) allocate(flm(0:lmax,0:lmax))
145 call mpi_barrier(icomm,ierrmpi)
146 if(npe>1) call mpi_bcast(flm,(lmax+1)*(lmax+1),mpi_double_complex,0,&
148 end if
149 if(mype==0) print*,'lmax=',lmax,'trunc=',trunc
150 nlarr=501
151 allocate(lmaxarray(nlarr))
152 allocate(xrg(nlarr))
153 lmaxarray=lmax
154 if(trunc) then
155 dxr=(r_s-r_0)/dble(nlarr-1)
156 do ir=1,nlarr
157 xrg(ir)=dxr*dble(ir-1)+r_0
158 do il=0,lmax
159 xrl=xrg(ir)**il
160 if(xrl > 1.d6) then
161 lmaxarray(ir)=il
162 exit
163 end if
164 end do
165 end do
166 endif
167 ! calculate global Alm Blm Rlm
168 allocate(alm(0:lmax,0:lmax))
169 allocate(blm(0:lmax,0:lmax))
170 allocate(rlm(0:lmax,0:lmax))
171 alm=(0.d0,0.d0)
172 blm=(0.d0,0.d0)
173 do l=0,lmax
174 do m=0,l
175 rsl=r_s**(-(2*l+1))
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)
179 end do
180 end do
181
182 end subroutine harm_coef
183
184 subroutine cfweights_cell_area(ym,theta,cfwm)
186
187 integer, intent(in) :: ym
188 double precision, intent(in) :: theta(ym)
189 double precision, intent(out) :: cfwm(ym)
190
191 double precision,dimension(ym) :: miu
192 double precision :: edge_l,edge_r
193 integer :: i
194
195 miu=dcos(theta)
196 if(miu(1)<=miu(ym)) then
197 do i=1,ym
198 if(i==1) then
199 edge_l=-1.d0
200 else
201 edge_l=0.5d0*(miu(i-1)+miu(i))
202 end if
203 if(i==ym) then
204 edge_r=1.d0
205 else
206 edge_r=0.5d0*(miu(i)+miu(i+1))
207 end if
208 cfwm(i)=dabs(edge_r-edge_l)*(2.d0*dpi)
209 end do
210 else
211 do i=1,ym
212 if(i==1) then
213 edge_l=1.d0
214 else
215 edge_l=0.5d0*(miu(i-1)+miu(i))
216 end if
217 if(i==ym) then
218 edge_r=-1.d0
219 else
220 edge_r=0.5d0*(miu(i)+miu(i+1))
221 end if
222 cfwm(i)=dabs(edge_r-edge_l)*(2.d0*dpi)
223 end do
224 end if
225
226 end subroutine cfweights_cell_area
227
228 subroutine cfweights_gauss_legendre(ym,miu,cfwm)
230
231 integer, intent(in) :: ym
232 double precision, intent(in) :: miu(ym)
233 double precision, intent(out) :: cfwm(ym)
234
235 double precision,dimension(ym) :: pl,pm2,pm1,pprime,sintheta
236 double precision :: lr
237 integer :: l
238
239 sintheta=dsqrt(1.d0-miu**2)
240
241 pm2=1.d0
242 pm1=miu
243
244 do l=2,ym-1
245 lr=1.d0/dble(l)
246 pl=(2.d0-lr)*pm1*miu-(1.d0-lr)*pm2
247 pm2=pm1
248 pm1=pl
249 end do
250
251 pprime=(dble(ym)*pl)/sintheta**2
252 cfwm=2.d0/(sintheta*pprime)**2
253 cfwm=cfwm*(2.d0*dpi)
254
255 end subroutine cfweights_gauss_legendre
256
257 subroutine coef(b_r0,xm,ym,miu,mius,cfwm)
259
260 integer, intent(in) :: xm,ym
261 double precision, intent(in) :: b_r0(xm,ym),cfwm(ym),miu(ym),mius(ym)
262
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
269
270 bm=(0.d0,0.d0)
271 do i=1,ym
272 fftmr=b_r0(:,i)/dble(xm)
273 fftmi=0.d0
274 call fft(fftmr,fftmi,xm,xm,xm,-1)
275 bm(:,i-1)=(fftmr+(0.d0,1.d0)*fftmi)
276 end do
277 n_mm(0)=1.d0/dsqrt(4.d0*dpi)
278 do m=1,lmax
279 n_mm(m)=-n_mm(m-1)*dsqrt(1.d0+1.d0/dble(2*m))
280 end do
281 !first do m=0
282 p_lm2=n_mm(0)
283 p_lm1=p_lm2*miu*dsqrt(3.d0)
284 !set l=0 m=0 term
285 flm(0,0)=sum(bm(0,:)*p_lm2*cfwm)
286 !set l=1 m=0 term
287 flm(1,0)=sum(bm(0,:)*p_lm1*cfwm)
288 do l=2,lmax
289 lr=dble(l)
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
293 !set m=0 term for all other l's
294 flm(l,0)=sum(bm(0,:)*p_l*cfwm)
295 p_lm2=p_lm1
296 p_lm1=p_l
297 end do
298
299 !since only l modes from 0 to lmax are used
300 bm=2.d0*bm
301
302 !now the rest of the m's
303 old_pmm=n_mm(0)
304 do m=1,lmax
305 p_lm2=old_pmm*mius*n_mm(m)/n_mm(m-1)
306 p_lm1=p_lm2*miu*dsqrt(dble(2*m+3))
307 !ACCURATE UP TO HERE
308 old_pmm=p_lm2
309 !set l=m mode
310 flm(m,m)=sum(bm(m,:)*p_lm2*cfwm)
311 !set l=m+1 mode
312 if(m<lmax) flm(m+1,m)=sum(bm(m,:)*p_lm1*cfwm)
313 mr=dble(m)
314 do l=m+2,lmax
315 lr=dble(l)
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-&
318 mr**2)))
319 p_l=c1*miu*p_lm1+c2*p_lm2
320 flm(l,m)=sum(bm(m,:)*p_l*cfwm)
321 p_lm2=p_lm1
322 p_lm1=p_l
323 end do
324 end do
325
326 end subroutine coef
327{^ifthreed
328 subroutine pfss(ixI^L,ixO^L,Bpf,x)
330
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)
334
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
340
341 bt=(0.d0,0.d0)
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)
349 if(trunc) then
350 do ir=1,size(lmaxarray)
351 if(xrg(ir)>=xr) exit
352 end do
353 if(ir>size(lmaxarray)) ir=size(lmaxarray)
354 qlmax=lmaxarray(ir)
355 else
356 qlmax=lmax
357 endif
358 !Calculate Br
359 do l=0,lmax
360 do m=0,l
361 bt(l,m,ix1)=alm(l,m)*dble(l)*xr**(l-1)-blm(l,m)*dble(l+1)*xr**(-l-2)
362 end do
363 enddo
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)
369 enddo
370 enddo
371 !Calculate Btheta
372 do l=0,lmax
373 do m=0,l
374 if (l==0) then
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))
382 else
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))
385 end if
386 end do
387 enddo
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(&
393 ixomax2-ix2+ixomin2)
394 enddo
395 enddo
396
397 !Calculate Bphi
398 do l=0,lmax
399 do m=0,l
400 bt(l,m,ix1)=(0.d0,1.d0)*m*(alm(l,m)*xr**(l-1)+blm(l,m)*xr**(-l-2))
401 end do
402 enddo
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(&
408 ixomax2-ix2+ixomin2)
409 enddo
410 enddo
411 enddo
412 !Scalar Potential
413 ! Potlc(ix^D)=Alm(l,m)*x(ix^D,1)**l+Blm(l,m)*x(ix^D,1)**(-l-1)
414
415 !do ix3=ixOmin3,ixOmax3
416 ! do ix2=ixOmin2,ixOmax2
417 ! print*,x(ix1,ixOmax2-ix2+ixOmin2,ix3,2)
418 ! print*,'miu==',miu(ixOmax2-ix2+ixOmin2)
419 ! enddo
420 !enddo
421
422 end subroutine pfss
423
424 subroutine inv_sph_transform(Bt,phi,miu,mius,nphi,ntheta,Bpf,qlmax)
426
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)
431
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
438
439 bamp=abs(bt)
440
441 phase=atan2(dimag(bt),dble(bt))
442
443 bpf=0.d0
444 !take care of modes where m=0
445 cp_0_0=dsqrt(1.d0/(4.d0*dpi))
446 !start with l=m=0 mode
447 bpf=bpf+bamp(0,0)*dcos(phase(0,0))*cp_0_0
448
449 !proceed with l=1 m=0 mode
450 cp_1_0=dsqrt(3.d0)*miu*cp_0_0
451 do iph=1,nphi
452 bpf(iph,:)=bpf(iph,:)+bamp(1,0)*dcos(phase(1,0))*cp_1_0
453 enddo
454
455 !proceed with l modes for which m=0
456 cp_lm1_0=cp_0_0
457 cp_l_0=cp_1_0
458 do l=2,qlmax
459 ld=dble(l)
460 cp_lm2_0=cp_lm1_0
461 cp_lm1_0=cp_l_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
465 do iph=1,nphi
466 bpf(iph,:)=bpf(iph,:)+bamp(l,0)*dcos(phase(l,0))*cp_l_0
467 enddo
468 enddo
469
470 !loop through m's for m>0 and then loop through l's for each m
471 cp_m_m=cp_0_0
472 do m=1,qlmax
473 md=dble(m)
474 !first do l=m modes
475 cp_m_m=-dsqrt(1.d0+1.d0/(2.d0*md))*mius*cp_m_m
476 do iph=1,nphi
477 angpart(iph)=dcos(md*phi(iph)+phase(m,m))
478 end do
479 do ith=1,ntheta
480 do iph=1,nphi
481 bpf(iph,ith)=bpf(iph,ith)+bamp(m,m)*angpart(iph)*cp_m_m(ith)
482 enddo
483 enddo
484
485 !proceed with l=m+1 modes
486 if(qlmax>=m+1) then
487 cp_mp1_m=dsqrt(2.d0*md+3.d0)*miu*cp_m_m
488 angpart=dcos(md*phi+phase(m+1,m))
489 do ith=1,ntheta
490 do iph=1,nphi
491 bpf(iph,ith)=bpf(iph,ith)+bamp(m+1,m)*angpart(iph)*cp_mp1_m(ith)
492 enddo
493 enddo
494 endif
495
496 !finish with the rest l
497 if(qlmax>=m+2) then
498 cp_lm1_m=cp_m_m
499 cp_l_m=cp_mp1_m
500 do l=m+2,qlmax
501 ld=dble(l)
502 cp_lm2_m=cp_lm1_m
503 cp_lm1_m=cp_l_m
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))
508 do ith=1,ntheta
509 do iph=1,nphi
510 bpf(iph,ith)=bpf(iph,ith)+bamp(l,m)*angpart(iph)*cp_l_m(ith)
511 enddo
512 enddo
513 enddo
514 endif
515 enddo
516
517 end subroutine inv_sph_transform
518}
519 subroutine fft(a,b,ntot,n,nspan,isn)
520 ! multivariate complex fourier transform, computed in place
521 ! using mixed-radix fast fourier transform algorithm.
522 ! by r. c. singleton, stanford research institute, sept. 1968
523 ! arrays a and b originally hold the real and imaginary
524 ! components of the data, and return the real and
525 ! imaginary components of the resulting fourier coefficients.
526 ! multivariate data is indexed according to the fortran
527 ! array element successor function, without limit
528 ! on the number of implied multiple subscripts.
529 ! the subroutine is called once for each variate.
530 ! the calls for a multivariate transform may be in any order.
531 ! ntot is the total number of complex data values.
532 ! n is the dimension of the current variable.
533 ! nspan/n is the spacing of consecutive data values
534 ! while indexing the current variable.
535 ! the sign of isn determines the sign of the complex
536 ! exponential, and the magnitude of isn is normally one.
537 ! a tri-variate transform with a(n1,n2,n3), b(n1,n2,n3)
538 ! is computed by
539 ! call fft(a,b,n1*n2*n3,n1,n1,1)
540 ! call fft(a,b,n1*n2*n3,n2,n1*n2,1)
541 ! call fft(a,b,n1*n2*n3,n3,n1*n2*n3,1)
542 ! for a single-variate transform,
543 ! ntot = n = nspan = (number of complex data values), e.g.
544 ! call fft(a,b,n,n,n,1)
545 ! the data can alternatively be stored in a single complex array c
546 ! in standard fortran fashion, i.e. alternating real and imaginary
547 ! parts. then with most fortran compilers, the complex array c can
548 ! be equivalenced to a real array a, the magnitude of isn changed
549 ! to two to give correct indexing increment, and a(1) and a(2) used
550 ! to pass the initial addresses for the sequences of real and
551 ! imaginary values, e.g.
552 ! complex c(ntot)
553 ! real a(2*ntot)
554 ! equivalence (c(1),a(1))
555 ! call fft(a(1),a(2),ntot,n,nspan,2)
556 ! arrays at(maxf), ck(maxf), bt(maxf), sk(maxf), and np(maxp)
557 ! are used for temporary storage. if the available storage
558 ! is insufficient, the program is terminated by a stop.
559 ! maxf must be .ge. the maximum prime factor of n.
560 ! maxp must be .gt. the number of prime factors of n.
561 ! in addition, if the square-free portion k of n has two or
562 ! more prime factors, then maxp must be .ge. k-1.
563 double precision :: a(:),b(:)
564 ! array storage in nfac for a maximum of 15 prime factors of n.
565 ! if n has more than one square-free factor, the product of the
566 ! square-free factors must be .le. 210
567 dimension nfac(11),np(209)
568 ! array storage for maximum prime factor of 23
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
575 equivalence(i,ii)
576
577 ! the following two constants should agree with the array dimensions.
578 maxp=209
579 ! Date: Wed, 9 Aug 1995 09:38:49 -0400
580 ! From: ldm@apollo.numis.nwu.edu
581 maxf=23
582 s3=0.d0
583 s2=0.d0
584 c3=0.d0
585 c2=0.d0
586 if(n .lt. 2) return
587 inc=isn
588 c72=0.30901699437494742d0
589 s72=0.95105651629515357d0
590 s120=0.86602540378443865d0
591 rad=6.2831853071796d0
592 if(isn .ge. 0) go to 10
593 s72=-s72
594 s120=-s120
595 rad=-rad
596 inc=-inc
597 10 nt=inc*ntot
598 ks=inc*nspan
599 kspan=ks
600 nn=nt-inc
601 jc=ks/n
602 radf=rad*dble(jc)*0.5d0
603 i=0
604 jf=0
605 ! determine the factors of n
606 m=0
607 k=n
608 go to 20
609 15 m=m+1
610 nfac(m)=4
611 k=k/16
612 20 if(k-(k/16)*16 .eq. 0) go to 15
613 j=3
614 jj=9
615 go to 30
616 25 m=m+1
617 nfac(m)=j
618 k=k/jj
619 30 if(mod(k,jj) .eq. 0) go to 25
620 j=j+2
621 jj=j**2
622 if(jj .le. k) go to 30
623 if(k .gt. 4) go to 40
624 kt=m
625 nfac(m+1)=k
626 if(k .ne. 1) m=m+1
627 go to 80
628 40 if(k-(k/4)*4 .ne. 0) go to 50
629 m=m+1
630 nfac(m)=2
631 k=k/4
632 50 kt=m
633 j=2
634 60 if(mod(k,j) .ne. 0) go to 70
635 m=m+1
636 nfac(m)=j
637 k=k/j
638 70 j=((j+1)/2)*2+1
639 if(j .le. k) go to 60
640 80 if(kt .eq. 0) go to 100
641 j=kt
642 90 m=m+1
643 nfac(m)=nfac(j)
644 j=j-1
645 if(j .ne. 0) go to 90
646 ! compute fourier transform
647 100 sd=radf/dble(kspan)
648 cd=2.d0*dsin(sd)**2
649 sd=dsin(sd+sd)
650 kk=1
651 i=i+1
652 if(nfac(i) .ne. 2) go to 400
653 ! transform for factor of 2 (including rotation factor)
654 kspan=kspan/2
655 k1=kspan+2
656 210 k2=kk+kspan
657 ak=a(k2)
658 bk=b(k2)
659 a(k2)=a(kk)-ak
660 b(k2)=b(kk)-bk
661 a(kk)=a(kk)+ak
662 b(kk)=b(kk)+bk
663 kk=k2+kspan
664 if(kk .le. nn) go to 210
665 kk=kk-nn
666 if(kk .le. jc) go to 210
667 if(kk .gt. kspan) go to 800
668 220 c1=1.d0-cd
669 s1=sd
670 230 k2=kk+kspan
671 ak=a(kk)-a(k2)
672 bk=b(kk)-b(k2)
673 a(kk)=a(kk)+a(k2)
674 b(kk)=b(kk)+b(k2)
675 a(k2)=c1*ak-s1*bk
676 b(k2)=s1*ak+c1*bk
677 kk=k2+kspan
678 if(kk .lt. nt) go to 230
679 k2=kk-nt
680 c1=-c1
681 kk=k1-k2
682 if(kk .gt. k2) go to 230
683 ak=c1-(cd*c1+sd*s1)
684 s1=(sd*c1-cd*s1)+s1
685 c1=2.d0-(ak**2+s1**2)
686 s1=c1*s1
687 c1=c1*ak
688 kk=kk+jc
689 if(kk .lt. k2) go to 230
690 k1=k1+inc+inc
691 kk=(k1-kspan)/2+jc
692 if(kk .le. jc+jc) go to 220
693 go to 100
694 ! transform for factor of 3 (optional code)
695 320 k1=kk+kspan
696 k2=k1+kspan
697 ak=a(kk)
698 bk=b(kk)
699 aj=a(k1)+a(k2)
700 bj=b(k1)+b(k2)
701 a(kk)=ak+aj
702 b(kk)=bk+bj
703 ak=-0.5d0*aj+ak
704 bk=-0.5d0*bj+bk
705 aj=(a(k1)-a(k2))*s120
706 bj=(b(k1)-b(k2))*s120
707 a(k1)=ak-bj
708 b(k1)=bk+aj
709 a(k2)=ak+bj
710 b(k2)=bk-aj
711 kk=k2+kspan
712 if(kk .lt. nn) go to 320
713 kk=kk-nn
714 if(kk .le. kspan) go to 320
715 go to 700
716 ! transform for factor of 4
717 400 if(nfac(i) .ne. 4) go to 600
718 kspnn=kspan
719 kspan=kspan/4
720 410 c1=1.d0
721 s1=0.d0
722 420 k1=kk+kspan
723 k2=k1+kspan
724 k3=k2+kspan
725 akp=a(kk)+a(k2)
726 akm=a(kk)-a(k2)
727 ajp=a(k1)+a(k3)
728 ajm=a(k1)-a(k3)
729 a(kk)=akp+ajp
730 ajp=akp-ajp
731 bkp=b(kk)+b(k2)
732 bkm=b(kk)-b(k2)
733 bjp=b(k1)+b(k3)
734 bjm=b(k1)-b(k3)
735 b(kk)=bkp+bjp
736 bjp=bkp-bjp
737 if(isn .lt. 0) go to 450
738 akp=akm-bjm
739 akm=akm+bjm
740 bkp=bkm+ajm
741 bkm=bkm-ajm
742 if(s1 .eq. 0.d0) go to 460
743 430 a(k1)=akp*c1-bkp*s1
744 b(k1)=akp*s1+bkp*c1
745 a(k2)=ajp*c2-bjp*s2
746 b(k2)=ajp*s2+bjp*c2
747 a(k3)=akm*c3-bkm*s3
748 b(k3)=akm*s3+bkm*c3
749 kk=k3+kspan
750 if(kk .le. nt) go to 420
751 440 c2=c1-(cd*c1+sd*s1)
752 s1=(sd*c1-cd*s1)+s1
753 c1=2.d0-(c2**2+s1**2)
754 s1=c1*s1
755 c1=c1*c2
756 c2=c1**2-s1**2
757 s2=2.d0*c1*s1
758 c3=c2*c1-s2*s1
759 s3=c2*s1+s2*c1
760 kk=kk-nt+jc
761 if(kk .le. kspan) go to 420
762 kk=kk-kspan+inc
763 if(kk .le. jc) go to 410
764 if(kspan .eq. jc) go to 800
765 go to 100
766 450 akp=akm+bjm
767 akm=akm-bjm
768 bkp=bkm-ajm
769 bkm=bkm+ajm
770 if(s1 .ne. 0) go to 430
771 460 a(k1)=akp
772 b(k1)=bkp
773 a(k2)=ajp
774 b(k2)=bjp
775 a(k3)=akm
776 b(k3)=bkm
777 kk=k3+kspan
778 if(kk .le. nt) go to 420
779 go to 440
780 ! transform for factor of 5 (optional code)
781 510 c2=c72**2-s72**2
782 s2=2.d0*c72*s72
783 520 k1=kk+kspan
784 k2=k1+kspan
785 k3=k2+kspan
786 k4=k3+kspan
787 akp=a(k1)+a(k4)
788 akm=a(k1)-a(k4)
789 bkp=b(k1)+b(k4)
790 bkm=b(k1)-b(k4)
791 ajp=a(k2)+a(k3)
792 ajm=a(k2)-a(k3)
793 bjp=b(k2)+b(k3)
794 bjm=b(k2)-b(k3)
795 aa=a(kk)
796 bb=b(kk)
797 a(kk)=aa+akp+ajp
798 b(kk)=bb+bkp+bjp
799 ak=akp*c72+ajp*c2+aa
800 bk=bkp*c72+bjp*c2+bb
801 aj=akm*s72+ajm*s2
802 bj=bkm*s72+bjm*s2
803 a(k1)=ak-bj
804 a(k4)=ak+bj
805 b(k1)=bk+aj
806 b(k4)=bk-aj
807 ak=akp*c2+ajp*c72+aa
808 bk=bkp*c2+bjp*c72+bb
809 aj=akm*s2-ajm*s72
810 bj=bkm*s2-bjm*s72
811 a(k2)=ak-bj
812 a(k3)=ak+bj
813 b(k2)=bk+aj
814 b(k3)=bk-aj
815 kk=k4+kspan
816 if(kk .lt. nn) go to 520
817 kk=kk-nn
818 if(kk .le. kspan) go to 520
819 go to 700
820 ! transform for odd factors
821 600 k=nfac(i)
822 kspnn=kspan
823 kspan=kspan/k
824 if(k .eq. 3) go to 320
825 if(k .eq. 5) go to 510
826 if(k .eq. jf) go to 640
827 jf=k
828 s1=rad/dble(k)
829 c1=dcos(s1)
830 s1=dsin(s1)
831 if(jf .gt. maxf) go to 998
832 ck(jf)=1.d0
833 sk(jf)=0.d0
834 j=1
835 630 ck(j)=ck(k)*c1+sk(k)*s1
836 sk(j)=ck(k)*s1-sk(k)*c1
837 k=k-1
838 ck(k)=ck(j)
839 sk(k)=-sk(j)
840 j=j+1
841 if(j .lt. k) go to 630
842 640 k1=kk
843 k2=kk+kspnn
844 aa=a(kk)
845 bb=b(kk)
846 ak=aa
847 bk=bb
848 j=1
849 k1=k1+kspan
850 650 k2=k2-kspan
851 j=j+1
852 at(j)=a(k1)+a(k2)
853 ak=at(j)+ak
854 bt(j)=b(k1)+b(k2)
855 bk=bt(j)+bk
856 j=j+1
857 at(j)=a(k1)-a(k2)
858 bt(j)=b(k1)-b(k2)
859 k1=k1+kspan
860 if(k1 .lt. k2) go to 650
861 a(kk)=ak
862 b(kk)=bk
863 k1=kk
864 k2=kk+kspnn
865 j=1
866 660 k1=k1+kspan
867 k2=k2-kspan
868 jj=j
869 ak=aa
870 bk=bb
871 aj=0.d0
872 bj=0.d0
873 k=1
874 670 k=k+1
875 ak=at(k)*ck(jj)+ak
876 bk=bt(k)*ck(jj)+bk
877 k=k+1
878 aj=at(k)*sk(jj)+aj
879 bj=bt(k)*sk(jj)+bj
880 jj=jj+j
881 if(jj .gt. jf) jj=jj-jf
882 if(k .lt. jf) go to 670
883 k=jf-j
884 a(k1)=ak-bj
885 b(k1)=bk+aj
886 a(k2)=ak+bj
887 b(k2)=bk-aj
888 j=j+1
889 if(j .lt. k) go to 660
890 kk=kk+kspnn
891 if(kk .le. nn) go to 640
892 kk=kk-nn
893 if(kk .le. kspan) go to 640
894 ! multiply by rotation factor (except for factors of 2 and 4)
895 700 if(i .eq. m) go to 800
896 kk=jc+1
897 710 c2=1.d0-cd
898 s1=sd
899 720 c1=c2
900 s2=s1
901 kk=kk+kspan
902 730 ak=a(kk)
903 a(kk)=c2*ak-s2*b(kk)
904 b(kk)=s2*ak+c2*b(kk)
905 kk=kk+kspnn
906 if(kk .le. nt) go to 730
907 ak=s1*s2
908 s2=s1*c2+c1*s2
909 c2=c1*c2-ak
910 kk=kk-nt+kspan
911 if(kk .le. kspnn) go to 730
912 c2=c1-(cd*c1+sd*s1)
913 s1=s1+(sd*c1-cd*s1)
914 c1=2.d0-(c2**2+s1**2)
915 s1=c1*s1
916 c2=c1*c2
917 kk=kk-kspnn+jc
918 if(kk .le. kspan) go to 720
919 kk=kk-kspan+jc+inc
920 if(kk .le. jc+jc) go to 710
921 go to 100
922 ! permute the results to normal order---done in two stages
923 ! permutation for square factors of n
924 800 np(1)=ks
925 if(kt .eq. 0) go to 890
926 k=kt+kt+1
927 if(m .lt. k) k=k-1
928 j=1
929 np(k+1)=jc
930 810 np(j+1)=np(j)/nfac(j)
931 np(k)=np(k+1)*nfac(j)
932 j=j+1
933 k=k-1
934 if(j .lt. k) go to 810
935 k3=np(k+1)
936 kspan=np(2)
937 kk=jc+1
938 k2=kspan+1
939 j=1
940 if(n .ne. ntot) go to 850
941 ! permutation for single-variate transform (optional code)
942 820 ak=a(kk)
943 a(kk)=a(k2)
944 a(k2)=ak
945 bk=b(kk)
946 b(kk)=b(k2)
947 b(k2)=bk
948 kk=kk+inc
949 k2=kspan+k2
950 if(k2 .lt. ks) go to 820
951 830 k2=k2-np(j)
952 j=j+1
953 k2=np(j+1)+k2
954 if(k2 .gt. np(j)) go to 830
955 j=1
956 840 if(kk .lt. k2) go to 820
957 kk=kk+inc
958 k2=kspan+k2
959 if(k2 .lt. ks) go to 840
960 if(kk .lt. ks) go to 830
961 jc=k3
962 go to 890
963 ! permutation for multivariate transform
964 850 k=kk+jc
965 860 ak=a(kk)
966 a(kk)=a(k2)
967 a(k2)=ak
968 bk=b(kk)
969 b(kk)=b(k2)
970 b(k2)=bk
971 kk=kk+inc
972 k2=k2+inc
973 if(kk .lt. k) go to 860
974 kk=kk+ks-jc
975 k2=k2+ks-jc
976 if(kk .lt. nt) go to 850
977 k2=k2-nt+kspan
978 kk=kk-nt+jc
979 if(k2 .lt. ks) go to 850
980 870 k2=k2-np(j)
981 j=j+1
982 k2=np(j+1)+k2
983 if(k2 .gt. np(j)) go to 870
984 j=1
985 880 if(kk .lt. k2) go to 850
986 kk=kk+jc
987 k2=kspan+k2
988 if(k2 .lt. ks) go to 880
989 if(kk .lt. ks) go to 870
990 jc=k3
991 890 if(2*kt+1 .ge. m) return
992 kspnn=np(kt+1)
993 ! permutation for square-free factors of n
994 j=m-kt
995 nfac(j+1)=1
996 900 nfac(j)=nfac(j)*nfac(j+1)
997 j=j-1
998 if(j .ne. kt) go to 900
999 kt=kt+1
1000 nn=nfac(kt)-1
1001 if(nn .gt. maxp) go to 998
1002 jj=0
1003 j=0
1004 go to 906
1005 902 jj=jj-k2
1006 k2=kk
1007 k=k+1
1008 kk=nfac(k)
1009 904 jj=kk+jj
1010 if(jj .ge. k2) go to 902
1011 np(j)=jj
1012 906 k2=nfac(kt)
1013 k=kt+1
1014 kk=nfac(k)
1015 j=j+1
1016 if(j .le. nn) go to 904
1017 ! determine the permutation cycles of length greater than 1
1018 j=0
1019 go to 914
1020 910 k=kk
1021 kk=np(k)
1022 np(k)=-kk
1023 if(kk .ne. j) go to 910
1024 k3=kk
1025 914 j=j+1
1026 kk=np(j)
1027 if(kk .lt. 0) go to 914
1028 if(kk .ne. j) go to 910
1029 np(j)=-j
1030 if(j .ne. nn) go to 914
1031 maxf=inc*maxf
1032 ! reorder a and b, following the permutation cycles
1033 go to 950
1034 924 j=j-1
1035 if(np(j) .lt. 0) go to 924
1036 jj=jc
1037 926 kspan=jj
1038 if(jj .gt. maxf) kspan=maxf
1039 jj=jj-kspan
1040 k=np(j)
1041 kk=jc*k+ii+jj
1042 k1=kk+kspan
1043 k2=0
1044 928 k2=k2+1
1045 at(k2)=a(k1)
1046 bt(k2)=b(k1)
1047 k1=k1-inc
1048 if(k1 .ne. kk) go to 928
1049 932 k1=kk+kspan
1050 k2=k1-jc*(k+np(k))
1051 k=-np(k)
1052 936 a(k1)=a(k2)
1053 b(k1)=b(k2)
1054 k1=k1-inc
1055 k2=k2-inc
1056 if(k1 .ne. kk) go to 936
1057 kk=k2
1058 if(k .ne. j) go to 932
1059 k1=kk+kspan
1060 k2=0
1061 940 k2=k2+1
1062 a(k1)=at(k2)
1063 b(k1)=bt(k2)
1064 k1=k1-inc
1065 if(k1 .ne. kk) go to 940
1066 if(jj .ne. 0) go to 926
1067 if(j .ne. 1) go to 924
1068 950 j=k3+1
1069 nt=nt-kspnn
1070 ii=nt-inc+1
1071 if(nt .ge. 0) go to 924
1072 return
1073 ! error finish, insufficient array storage
1074 998 isn=0
1075 print 999
1076 stop
1077 999 format(44h0array bounds exceeded within subroutine fft)
1078 end subroutine fft
1079
1080end module mod_pfss
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...
Definition mod_pfss.t:40
character(len=20), public pfss_theta_quadrature
Definition mod_pfss.t:50
double precision, public r_0
Definition mod_pfss.t:46
subroutine, public pfss(ixil, ixol, bpf, x)
Definition mod_pfss.t:329
integer, public lmax
Definition mod_pfss.t:48
subroutine, public harm_coef(mapname)
Definition mod_pfss.t:60
logical, public trunc
Definition mod_pfss.t:49
double precision, public r_s
Definition mod_pfss.t:46