MPI-AMRVAC  3.0
The MPI - Adaptive Mesh Refinement - Versatile Advection Code
mod_lfff.t
Go to the documentation of this file.
1 !> Program to extrapolate linear force-free fields in 3D Cartesian coordinates,
2 !> based on exact Green function method (Chiu & Hilton 1977 ApJ 212,873).
3 !>
4 !> Usage:
5 !> 1 In the subroutine usr_set_parameters of mod_usr.t:
6 !> To extrapolate a linear force free field from a observed magnetogram
7 !> prepared in a data file, e.g., 'hmiM720sxxxx.dat' replace
8 !> call init_bc_fff_data('hmiM720sxxxx.dat',unit_length,unit_magneticfield)
9 !> 'hmiM720sxxxx.dat' must be a binary file containing nx1,nx2,xc1,xc2,dxm1,
10 !> dxm2, Bz0(nx1,nx2). Integers nx1 and nx2 give the resolution of the
11 !> uniform-grid magentogram. Others are double-precision floats. xc1 and xc2
12 !> are coordinates of the central point of the magnetogram. dxm1 and dxm2
13 !> are the cell sizes for each direction, Bz0 is the vertical conponent
14 !> of magetic field on the solar surface from observations.
15 !>2 In the subroutine usr_init_one_grid of mod_usr.t,
16 !> add lines like:
17 !>
18 !> double precision :: Bf(ixG^S,1:ndir), alpha, zshift
19 !>
20 !> alpha=0.d0 ! potential field
21 !> !alpha=0.08d0 ! non-potential linear force-free field
22 !> zshift=0.05d0 ! lift your box zshift heigher to the bottom magnetogram
23 !> call calc_lin_fff(ixG^L,ix^L,Bf,x,alpha,zshift)
24 !>
25 !>3 Notice that the resolution of input magnetogram must be better than the best
26 !> resolution of your AMR grid to have a good behavior close to the bottom layer
27 module mod_lfff
28  implicit none
29 
30  integer, save :: nx1,nx2
31  double precision, save :: bzmax,darea
32  double precision, allocatable, save :: bz0(:,:)
33  double precision, allocatable, save :: xa1(:),xa2(:)
34 
35 contains
36 
37  subroutine init_b_fff_data(magnetogramname,qLunit,qBunit)
39 
40  double precision, intent(in) :: qLunit,qBunit
41  double precision :: xc1,xc2,dxm1,dxm2
42  integer, dimension(MPI_STATUS_SIZE) :: statuss
43  integer :: file_handle,i
44  character(len=*), intent(in) :: magnetogramname
45  logical :: aexist
46  ! nx1,nx2 are numbers of cells for each direction
47  ! xc1,xc2 are coordinates of the central point of the magnetogram
48  ! dxm1,dxm2 are cell sizes for each direction
49  ! Bz0 is the 2D Bz magnetogram
50  inquire(file=magnetogramname,exist=aexist)
51  if(.not. aexist) then
52  if(mype==0) write(*,'(2a)') "can not find file:",magnetogramname
53  call mpistop("no input magnetogram----init_b_fff_data")
54  end if
55  call mpi_file_open(icomm,magnetogramname,mpi_mode_rdonly,mpi_info_null,&
56  file_handle,ierrmpi)
57  call mpi_file_read_all(file_handle,nx1,1,mpi_integer,statuss,ierrmpi)
58  call mpi_file_read_all(file_handle,nx2,1,mpi_integer,statuss,ierrmpi)
59  allocate(bz0(nx1,nx2))
60  call mpi_file_read_all(file_handle,xc1,1,mpi_double_precision,statuss,ierrmpi)
61  call mpi_file_read_all(file_handle,xc2,1,mpi_double_precision,statuss,ierrmpi)
62  call mpi_file_read_all(file_handle,dxm1,1,mpi_double_precision,statuss,ierrmpi)
63  call mpi_file_read_all(file_handle,dxm2,1,mpi_double_precision,statuss,ierrmpi)
64  call mpi_file_read_all(file_handle,bz0,nx1*nx2,mpi_double_precision,&
65  statuss,ierrmpi)
66  call mpi_file_close(file_handle,ierrmpi)
67  allocate(xa1(nx1))
68  allocate(xa2(nx2))
69  do i=1,nx1
70  xa1(i) = xc1 + (dble(i) - dble(nx1)/2.d0 - 0.5d0)*dxm1
71  enddo
72  do i=1,nx2
73  xa2(i) = xc2 + (dble(i) - dble(nx2)/2.d0 - 0.5d0)*dxm2
74  enddo
75  ! declare and define global variables Lunit and Bunit to be your length unit in
76  ! cm and magnetic strength unit in Gauss first
77  dxm1=dxm1/qlunit
78  dxm2=dxm2/qlunit
79  xa1=xa1/qlunit
80  xa2=xa2/qlunit
81  darea=dxm1*dxm2
82  bz0=bz0/qbunit
83  bzmax=maxval(dabs(bz0(:,:)))
84 
85  ! normalize b
86  bz0=bz0/bzmax
87  if(mype==0) then
88  print*,'magnetogram xrange:',minval(xa1),maxval(xa1)
89  print*,'magnetogram yrange:',minval(xa2),maxval(xa2)
90  end if
91 
92  if(mype==0) then
93  print*,'extrapolating 3D force-free field from an observed Bz '
94  print*,'magnetogram of',nx1,'by',nx2,'pixels. Bzmax=',bzmax
95  endif
96 
97  end subroutine init_b_fff_data
98 
99 {^ifthreed
100  subroutine calc_lin_fff(ixI^L,ixO^L,Bf,x,alpha,zshift,idir)
101  ! PURPOSE:
102  ! Calculation to determine linear FFF from the field on
103  ! the lower boundary (Chiu and Hilton 1977 ApJ 212,873).
104  ! NOTE: Only works for Cartesian coordinates
105  ! INPUT: Bf,x
106  ! OUTPUT: updated b in w
108 
109  integer, intent(in) :: ixI^L, ixO^L
110  integer, optional, intent(in) :: idir
111  double precision, intent(in) :: x(ixI^S,1:ndim),alpha,zshift
112  double precision, intent(inout) :: Bf(ixI^S,1:ndir)
113 
114  double precision, dimension(ixO^S) :: cos_az,sin_az,zk,bigr,r,r2,r3,cos_ar,sin_ar,g,dgdz
115  double precision :: gx(ixO^S,1:ndim),twopiinv
116  integer :: idim,ixp1,ixp2
117 
118  bf=0.d0
119  twopiinv = 0.5d0/dpi*bzmax*darea
120  ! get cos and sin arrays
121  zk(ixo^s)=x(ixo^s,3)-xprobmin3+zshift
122  cos_az(ixo^s)=dcos(alpha*zk(ixo^s))
123  sin_az(ixo^s)=dsin(alpha*zk(ixo^s))
124  ! looping Bz0 pixels
125  do ixp2=1,nx2
126  do ixp1=1,nx1
127  bigr(ixo^s)=dsqrt((x(ixo^s,1)-xa1(ixp1))**2+&
128  (x(ixo^s,2)-xa2(ixp2))**2)
129  r2=bigr**2+zk**2
130  r=dsqrt(r2)
131  r3=r**3
132  cos_ar=dcos(alpha*r)
133  sin_ar=dsin(alpha*r)
134  where(bigr/=0.d0)
135  bigr=1.d0/bigr
136  end where
137  where(r/=0.d0)
138  r=1.d0/r
139  end where
140  where(r2/=0.d0)
141  r2=1.d0/r2
142  end where
143  where(r3/=0.d0)
144  r3=1.d0/r3
145  end where
146  g=(zk*cos_ar*r-cos_az)*bigr
147  dgdz=(cos_ar*(r-zk**2*r3)-alpha*zk**2*sin_ar*r2+alpha*sin_az)*bigr
148  do idim=1,ndim
149  if(present(idir).and.idim/=idir) cycle
150  select case(idim)
151  case(1)
152  bf(ixo^s,1)=bf(ixo^s,1)+bz0(ixp1,ixp2)*((x(ixo^s,1)-xa1(ixp1))*dgdz(ixo^s)&
153  +alpha*g(ixo^s)*(x(ixo^s,2)-xa2(ixp2)))*bigr(ixo^s)
154  case(2)
155  bf(ixo^s,2)=bf(ixo^s,2)+bz0(ixp1,ixp2)*((x(ixo^s,2)-xa2(ixp2))*dgdz(ixo^s)&
156  -alpha*g(ixo^s)*(x(ixo^s,1)-xa1(ixp1)))*bigr(ixo^s)
157  case(3)
158  bf(ixo^s,3)=bf(ixo^s,3)+bz0(ixp1,ixp2)*(zk(ixo^s)*cos_ar(ixo^s)*r3(ixo^s)+alpha*&
159  zk(ixo^s)*sin_ar(ixo^s)*r2(ixo^s))
160  end select
161  end do
162  end do
163  end do
164  bf(ixo^s,:)=bf(ixo^s,:)*twopiinv
165 
166  end subroutine calc_lin_fff
167 
168  subroutine get_potential_field_potential(ixI^L,ixO^L,potential,x,zshift)
169  ! PURPOSE:
170  ! Calculation scalar potential of potential field given
171  ! Bz at photosphere (Schmidt 1964 NASSP).
172  ! NOTE: Only works for Cartesian coordinates
173  ! INPUT: x,zshift
174  ! OUTPUT: potential
176 
177  integer, intent(in) :: ixI^L, ixO^L
178  double precision, intent(in) :: x(ixI^S,1:ndim),zshift
179  double precision, intent(inout) :: potential(ixI^S)
180 
181  double precision, dimension(ixO^S) :: zk,bigr
182  integer :: ixp1,ixp2
183 
184  zk(ixo^s)=x(ixo^s,3)-xprobmin3+zshift
185  potential=0.d0
186  ! looping Bz0 pixels see equation (2)
187  do ixp2=1,nx2
188  do ixp1=1,nx1
189  bigr(ixo^s)=dsqrt((x(ixo^s,1)-xa1(ixp1))**2+&
190  (x(ixo^s,2)-xa2(ixp2))**2+&
191  zk(ixo^s)**2)
192  potential(ixo^s)=potential(ixo^s)+0.5d0*bz0(ixp1,ixp2)/bigr*darea/dpi
193  end do
194  end do
195  end subroutine get_potential_field_potential
196 }
197 end module mod_lfff
subroutine mpistop(message)
Exit MPI-AMRVAC with an error message.
Definition: comm_lib.t:194
This module contains definitions of global parameters and variables and some generic functions/subrou...
integer icomm
The MPI communicator.
integer mype
The rank of the current MPI task.
integer ierrmpi
A global MPI error return code.
Program to extrapolate linear force-free fields in 3D Cartesian coordinates, based on exact Green fun...
Definition: mod_lfff.t:27
double precision, save darea
Definition: mod_lfff.t:31
double precision, dimension(:,:), allocatable, save bz0
Definition: mod_lfff.t:32
subroutine get_potential_field_potential(ixIL, ixOL, potential, x, zshift)
Definition: mod_lfff.t:169
integer, save nx1
Definition: mod_lfff.t:30
integer, save nx2
Definition: mod_lfff.t:30
subroutine init_b_fff_data(magnetogramname, qLunit, qBunit)
Definition: mod_lfff.t:38
double precision, dimension(:), allocatable, save xa2
Definition: mod_lfff.t:33
subroutine calc_lin_fff(ixIL, ixOL, Bf, x, alpha, zshift, idir)
Definition: mod_lfff.t:101
double precision, save bzmax
Definition: mod_lfff.t:31
double precision, dimension(:), allocatable, save xa1
Definition: mod_lfff.t:33