PB3D  [2.45]
Ideal linear high-n MHD stability in 3-D
vac_vars.f90
Go to the documentation of this file.
1 !------------------------------------------------------------------------------!
3 !------------------------------------------------------------------------------!
4 module vac_vars
5 #include <PB3D_macros.h>
6  use strumpackdensepackage
7  use str_utilities
8  use messages
10  use grid_vars, only: grid_type
11 
12  implicit none
13 
14  private
16 #if ldebug
17  public n_alloc_vacs
18 #endif
19 
20  ! global variables
21  integer, parameter :: bs = 16
22 #if ldebug
23  integer :: n_alloc_vacs
24 #endif
25 
46  type, public :: vac_type
47  integer :: style
48  integer :: prim_x
49  integer :: ctxt_hg
50  integer :: n_bnd
51  integer :: bs
52  integer :: mpi_comm
53  integer :: desc_h(blacsctxtsize)
54  integer :: desc_g(blacsctxtsize)
55  integer :: n_p(2)
56  integer :: n_ang(2)
57  integer :: ind_p(2)
58  integer :: n_loc(2)
59  integer, allocatable :: sec_x(:)
60  integer, allocatable :: lims_c(:,:)
61  integer, allocatable :: lims_r(:,:)
62  real(dp) :: jq
63  real(dp), allocatable :: ang(:,:)
64  real(dp), allocatable :: norm(:,:)
65  real(dp), allocatable :: dnorm(:,:)
66  real(dp), allocatable :: h_fac(:,:)
67  real(dp), allocatable :: x_vec(:,:)
68  real(dp), allocatable :: h(:,:)
69  real(dp), allocatable :: g(:,:)
70  complex(dp), allocatable :: res(:,:)
71 #if ldebug
72  real(dp) :: estim_mem_usage
73 #endif
74  contains
76  procedure :: init => init_vac
78  procedure :: dealloc => dealloc_vac
79  end type
80 
81 contains
120  integer function init_vac(vac,style,n_bnd,prim_X,n_ang,jq) result(ierr)
121  use mpi
122  use num_vars, only: n_procs, rank
123  use x_vars, only: n_mod_x
124 #if ldebug
125  use num_vars, only: print_mem_usage
126 #endif
127 
128  character(*), parameter :: rout_name = 'init_vac'
129 
130  ! input / output
131  class(vac_type), intent(inout) :: vac
132  integer, intent(in) :: style
133  integer, intent(in) :: n_bnd
134  integer, intent(in) :: prim_x
135  integer, intent(in) :: n_ang(2)
136  real(dp), intent(in) :: jq
137 
138  ! local variables
139  character(len=max_str_ln) :: err_msg ! error message
140  integer :: n_dims ! number of dimensions to be saved in x_vec and norm
141  integer :: jd ! counter
142  integer, allocatable :: proc_map(:,:) ! process map
143 
144  ! initialize ierr
145  ierr = 0
146 
147 #if ldebug
148  ! initialize memory usage
149  if (print_mem_usage) vac%estim_mem_usage = 0._dp
150 #endif
151 
152  ! test
153  if (product(n_ang).ne.n_bnd) then
154  ierr = 1
155  err_msg = 'The total number of angles along B, '//&
156  &trim(i2str(product(n_ang)))//', is not equal to n_bnd = '//&
157  &trim(i2str(n_bnd))
158  chckerr(err_msg)
159  end if
160 
161  ! set some variables
162  vac%bs = bs
163  if (n_procs.eq.1) vac%bs = n_bnd
164  vac%jq = jq
165  vac%n_ang = n_ang
166 
167  ! Initialize the BLACS grid for H and G
168  vac%prim_X = prim_x
169  vac%n_bnd = n_bnd
170  vac%n_p(1)=floor(sqrt(n_procs*1._dp))
171  vac%n_p(2)=n_procs/vac%n_p(1)
172  allocate(proc_map(vac%n_p(1),vac%n_p(2)))
173  proc_map = transpose(reshape(&
174  &[(jd+n_procs-1-product(vac%n_p),jd=1,product(vac%n_p))],vac%n_p))
175  call blacs_get(0,0,vac%ctxt_HG)
176  call blacs_gridmap(vac%ctxt_HG,proc_map,vac%n_p(1),vac%n_p(1),&
177  &vac%n_p(2)) ! last MPI proc is also last process in map
178  call blacs_gridinfo(vac%ctxt_HG,vac%n_p(1),vac%n_p(2),vac%ind_p(1),&
179  &vac%ind_p(2)) ! get nr. of rows and columns and local index
180  if(minval(vac%ind_p).ge.0) then ! only the ranks that participate
181  do jd = 1,2 ! loop over rows, then columns
182  vac%n_loc(jd) = numroc(vac%n_bnd,vac%bs,vac%ind_p(jd),0,&
183  &vac%n_p(jd)) ! get local number of rows, then columns
184  end do
185  call descinit(vac%desc_H,n_bnd,n_bnd,vac%bs,vac%bs,0,0,vac%ctxt_HG,&
186  &max(1,vac%n_loc(1)),ierr)
187  chckerr('descinit failed')
188  call descinit(vac%desc_G,n_bnd,n_bnd,vac%bs,vac%bs,0,0,vac%ctxt_HG,&
189  &max(1,vac%n_loc(1)),ierr)
190  chckerr('descinit failed')
191  call mpi_comm_split(mpi_comm_world,1,rank,vac%MPI_Comm,ierr)
192  chckerr('')
193  else
194  vac%n_loc = [0,0]
195  call mpi_comm_split(mpi_comm_world,mpi_undefined,rank,&
196  &vac%MPI_Comm,ierr)
197  chckerr('')
198  end if
199 
200  ! set limits
201  call set_loc_lims(vac%n_loc(1),vac%bs,vac%ind_p(1),vac%n_p(1),&
202  &vac%lims_r)
203  call set_loc_lims(vac%n_loc(2),vac%bs,vac%ind_p(2),vac%n_p(2),&
204  &vac%lims_c)
205 
206  ! set n_dims
207  vac%style = style
208  select case (vac%style)
209  case (1) ! field-line 3-D
210  n_dims = 3
211  case (2) ! axisymmetric
212  n_dims = 2
213  case default
214  ierr = 1
215  err_msg = 'No vacuum style '//trim(i2str(vac%style))//&
216  &' possible'
217  chckerr(err_msg)
218  end select
219 
220  ! allocate normal and position vector
221  allocate(vac%norm(vac%n_bnd,n_dims))
222  allocate(vac%x_vec(vac%n_bnd,n_dims))
223 
224  ! allocate variables specific to style
225  select case (vac%style)
226  case (1) ! field-line 3-D
227  allocate(vac%h_fac(vac%n_bnd,4))
228  case (2) ! axisymmetric
229  allocate(vac%ang(n_ang(1),n_ang(2)))
230  allocate(vac%dnorm(vac%n_bnd,n_dims))
231  end select
232 
233  ! allocate vacuum response if last process
234  if (rank.eq.n_procs-1) allocate(vac%res(n_mod_x,n_mod_x))
235 
236  ! allocate H and G
237  allocate(vac%G(vac%n_loc(1),vac%n_loc(2)))
238  allocate(vac%H(vac%n_loc(1),vac%n_loc(2)))
239  vac%G = 0._dp
240  vac%H = 0._dp
241 
242 #if ldebug
243  ! set estimated memory usage
244  if (print_mem_usage) vac%estim_mem_usage = &
245  &vac%estim_mem_usage + size(vac%G) + n_mod_x**2
246 
247  ! increment n_alloc_vacs
249 
250  ! print memory usage
251  if (print_mem_usage) call writo('[rank '//trim(i2str(rank))//&
252  &' - Expected memory usage of vac: '//&
253  &trim(r2strt(vac%estim_mem_usage*weight_dp*2))//' kB]',alert=.true.)
254 #endif
255  end function init_vac
256 
260  subroutine set_loc_lims(n_loc,bs,ind_p,n_p,lims)
261  ! input / output
262  integer, intent(in) :: n_loc
263  integer, intent(in) :: bs
264  integer, intent(in) :: ind_p
265  integer, intent(in) :: n_p
266  integer, intent(inout), allocatable :: lims(:,:)
267 
268  ! local variables
269  integer :: jd ! counter
270 
271  ! set limits
272  if (n_loc.gt.0) then
273  allocate(lims(2,ceiling(n_loc*1._dp/bs)))
274  do jd = 1,size(lims,2)
275  lims(1,jd) = indxl2g((jd-1)*bs+1,bs,ind_p,0,n_p)
276  lims(2,jd) = indxl2g(min(jd*bs,n_loc),bs,ind_p,0,n_p)
277  end do
278  else
279  ! these processes don't play along
280  allocate(lims(2,1))
281  lims(:,1) = [0,-1]
282  end if
283  end subroutine set_loc_lims
284 
286  subroutine dealloc_vac(vac)
287 #if ldebug
288  use num_vars, only: rank, print_mem_usage
289 #endif
290 
291  ! input / output
292  class(vac_type), intent(inout) :: vac
293 
294 #if ldebug
295  ! local variables
296  integer :: mem_diff ! difference in memory
297  real(dp) :: estim_mem_usage ! estimated memory usage
298 
299  ! memory usage before deallocation
300  if (print_mem_usage) then
301  mem_diff = get_mem_usage()
302  estim_mem_usage = vac%estim_mem_usage
303  end if
304 #endif
305 
306  ! free grid
307  if (in_context(vac%ctxt_HG)) call blacs_gridexit(vac%ctxt_HG)
308 
309  ! deallocate allocatable variables
310  call dealloc_vac_final(vac)
311 
312 #if ldebug
313  ! decrement n_alloc_vacs
315 
316  ! memory usage difference after deallocation
317  if (print_mem_usage) then
318  mem_diff = mem_diff - get_mem_usage()
319  call writo('[Rank '//trim(i2str(rank))//' - liberated '//&
320  &trim(i2str(mem_diff))//'kB deallocating vac ('//&
321  &trim(i2str(nint(100*mem_diff/&
322  &(estim_mem_usage*weight_dp*2))))//&
323  &'% of estimated)]',alert=.true.)
324  end if
325 #endif
326  contains
327  ! Note: intent(out) automatically deallocates the variable
329  subroutine dealloc_vac_final(vac)
330  ! input / output
331  type(vac_type), intent(out) :: vac ! vacuum variables to be deallocated
332  end subroutine dealloc_vac_final
333  end subroutine dealloc_vac
334 
338  integer function copy_vac(vac,vac_copy) result(ierr)
339  use num_vars, only: rank, n_procs
340 
341  ! input / output
342  class(vac_type), intent(in) :: vac
343  class(vac_type), intent(inout) :: vac_copy
344 
345  character(*), parameter :: rout_name = 'copy_vac'
346 
347  ! initialize ierr
348  ierr = 0
349 
350  ! reallocate
351  ierr = vac_copy%init(vac%style,vac%n_bnd,vac%prim_X,vac%n_ang,&
352  &vac%jq)
353  chckerr('')
354 
355  ! copy normal and position vector
356  vac_copy%norm = vac%norm
357  vac_copy%x_vec = vac%x_vec
358 
359  ! copy variables specific to style
360  select case (vac%style)
361  case (1) ! field-line 3-D
362  vac_copy%h_fac = vac%h_fac
363  case (2) ! axisymmetric
364  vac_copy%dnorm = vac%dnorm
365  vac_copy%ang = vac%ang
366  end select
367 
368  ! copy vacuum response
369  if (rank.eq.n_procs-1) vac_copy%res = vac%res
370 
371  ! copy H and G
372  vac_copy%H = vac%H
373  vac_copy%G = vac%G
374  end function copy_vac
375 
377  logical function in_context(ctxt) result(res)
378  ! input / output
379  integer, intent(in) :: ctxt
380 
381  ! local variables
382  integer :: n_p(2) ! nr. of processes in grid
383  integer :: ind_p(2) ! index of local process in grid
384 
385  call blacs_gridinfo(ctxt,n_p(1),n_p(2),ind_p(1),ind_p(2))
386  res = ind_p(1).ge.0
387  end function in_context
388 end module vac_vars
num_vars::max_name_ln
integer, parameter, public max_name_ln
maximum length of filenames
Definition: num_vars.f90:51
num_vars::dp
integer, parameter, public dp
double precision
Definition: num_vars.f90:46
vac_vars::copy_vac
integer function, public copy_vac(vac, vac_copy)
Copy a vacuum type.
Definition: vac_vars.f90:339
num_vars
Numerical variables used by most other modules.
Definition: num_vars.f90:4
num_vars::max_str_ln
integer, parameter, public max_str_ln
maximum length of strings
Definition: num_vars.f90:50
str_utilities::i2str
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
Definition: str_utilities.f90:18
messages::get_mem_usage
integer function, public get_mem_usage()
Returns the memory usage in kilobytes.
Definition: messages.f90:554
num_vars::iu
complex(dp), parameter, public iu
complex unit
Definition: num_vars.f90:85
num_vars::n_procs
integer, public n_procs
nr. of MPI processes
Definition: num_vars.f90:69
str_utilities
Operations on strings.
Definition: str_utilities.f90:4
grid_vars::grid_type
Type for grids.
Definition: grid_vars.f90:59
str_utilities::r2strt
elemental character(len=max_str_ln) function, public r2strt(k)
Convert a real (double) to string.
Definition: str_utilities.f90:54
vac_vars
Variables pertaining to the vacuum quantities.
Definition: vac_vars.f90:4
num_vars::weight_dp
real(dp), parameter, public weight_dp
size of double precision in kB
Definition: num_vars.f90:49
vac_vars::set_loc_lims
subroutine, public set_loc_lims(n_loc, bs, ind_p, n_p, lims)
Calculates the limits in local index.
Definition: vac_vars.f90:261
vac_vars::dealloc_vac
subroutine dealloc_vac(vac)
Deallocates vacuum variables.
Definition: vac_vars.f90:287
vac_vars::n_alloc_vacs
integer, public n_alloc_vacs
nr. of allocated vacs
Definition: vac_vars.f90:23
num_vars::print_mem_usage
logical, public print_mem_usage
print memory usage is printed
Definition: num_vars.f90:149
x_vars
Variables pertaining to the perturbation quantities.
Definition: X_vars.f90:4
vac_vars::in_context
logical function, public in_context(ctxt)
Indicates whether current process is in the context.
Definition: vac_vars.f90:378
messages::writo
subroutine, public writo(input_str, persistent, error, warning, alert)
Write output to file identified by output_i.
Definition: messages.f90:275
messages
Numerical utilities related to giving output.
Definition: messages.f90:4
vac_vars::init_vac
integer function init_vac(vac, style, n_bnd, prim_X, n_ang, jq)
Initializes a vacuum type.
Definition: vac_vars.f90:121
vac_vars::vac_type
vacuum type
Definition: vac_vars.f90:46
grid_vars
Variables pertaining to the different grids used.
Definition: grid_vars.f90:4
x_vars::n_mod_x
integer, public n_mod_x
size of m_X (pol. flux) or n_X (tor. flux)
Definition: X_vars.f90:129
num_vars::rank
integer, public rank
MPI rank.
Definition: num_vars.f90:68