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