PB3D  [2.45]
Ideal linear high-n MHD stability in 3-D
X_utilities.f90
Go to the documentation of this file.
1 !------------------------------------------------------------------------------!
3 !------------------------------------------------------------------------------!
4 module x_utilities
5 #include <PB3D_macros.h>
6  use str_utilities
7  use messages
8  use num_vars, only: dp, max_name_ln, iu, max_str_ln
9  use grid_vars, only: grid_type
10  use x_vars, only: n_mod_x
11 
12  implicit none
13 
14  private
17 
18  ! interfaces
19 
22  interface sec_ind_loc2tot
24  module procedure sec_ind_loc2tot_1
26  module procedure sec_ind_loc2tot_2
27  end interface
28 
29 contains
31  function sec_ind_loc2tot_1(id,lim_sec_X) result(res)
32  ! input / output
33  integer, intent(in) :: id
34  integer, intent(in), optional :: lim_sec_x(2)
35  integer :: res
36 
37  ! local variables
38  integer :: lim_sec_x_loc(2) ! local lim_sec_X
39 
40  ! set local lim_sec_X
41  lim_sec_x_loc = [1,n_mod_x]
42  if (present(lim_sec_x)) lim_sec_x_loc = lim_sec_x
43 
44  ! set sec_ind_tot
45  res = lim_sec_x_loc(1)-1+id
46  end function sec_ind_loc2tot_1
48  function sec_ind_loc2tot_2(id,jd,lim_sec_X) result(res)
49  ! input / output
50  integer, intent(in) :: id
51  integer, intent(in) :: jd
52  integer, intent(in), optional :: lim_sec_x(2,2)
53  integer :: res(2)
54 
55  ! local variables
56  integer :: lim_sec_x_loc(2,2) ! local lim_sec_X
57 
58  ! set local lim_sec_X
59  lim_sec_x_loc(:,1) = [1,n_mod_x]
60  lim_sec_x_loc(:,2) = [1,n_mod_x]
61  if (present(lim_sec_x)) lim_sec_x_loc = lim_sec_x
62 
63  ! set sec_ind_tot
64  res = [lim_sec_x_loc(1,1)-1+id,lim_sec_x_loc(1,2)-1+jd]
65  end function sec_ind_loc2tot_2
66 
127  subroutine get_sec_x_range(sec_X_range_loc,sec_X_range_tot,m,sym,lim_sec_X)
128  use x_vars, only: n_mod_x
129  use num_utilities, only: c
130 
131  ! input / output
132  integer, intent(inout) :: sec_x_range_loc(2)
133  integer, intent(inout) :: sec_x_range_tot(2)
134  integer, intent(in) :: m
135  logical, intent(in) :: sym
136  integer, intent(in), optional :: lim_sec_x(2,2)
137 
138  ! local variables
139  integer :: k_range_loc(2) ! local range of k
140  integer :: k ! counter
141  integer :: n_mod ! local n_mod
142 
143  ! set number of modes of dimension 1
144  if (present(lim_sec_x)) then
145  n_mod = lim_sec_x(2,1)-lim_sec_x(1,1)+1
146  else
147  n_mod = n_mod_x
148  endif
149 
150  ! initialize secondary X range
151  k_range_loc = [n_mod+1,0] ! initialize to inverted values, out of bounds
152 
153  ! find start and end of k range
154  find_start: do k = 1,n_mod
155  if (is_necessary_x(sym,[k,m],lim_sec_x)) then ! first necessary pair [k,m]
156  k_range_loc(1) = k
157  exit find_start
158  end if
159  end do find_start
160  find_stop: do k = n_mod,k_range_loc(1),-1
161  if (is_necessary_x(sym,[k,m],lim_sec_x)) then ! last necessary pair [k,m]
162  k_range_loc(2) = k
163  exit find_stop
164  end if
165  end do find_stop
166 
167  ! translate k range and m value to 1-D index
168  do k = 1,2
169  sec_x_range_loc(k) = c([k_range_loc(k),m],sym,n_mod_x,lim_sec_x)
170  sec_x_range_tot(k) = c(sec_ind_loc2tot(k_range_loc(k),m,lim_sec_x),&
171  &sym,n_mod_x)
172  end do
173  end subroutine get_sec_x_range
174 
178  logical function do_x()
180 
181  ! increment perturbation job nr.
182  x_job_nr = x_job_nr + 1
183 
184  if (x_job_nr.le.size(x_jobs_lims,2)) then
185  do_x = .true.
186  else
187  do_x = .false.
188  end if
189  end function do_x
190 
196  logical function is_necessary_x(sym,sec_X_id,lim_sec_X) result(res)
197  ! input / output
198  logical, intent(in) :: sym
199  integer, intent(in) :: sec_x_id(2)
200  integer, intent(in), optional :: lim_sec_x(2,2)
201 
202  ! local variables
203  integer :: lim_sec_x_loc(2,2) ! local version of lim_sec_X
204 
205  ! initialize res
206  res = .true.
207 
208  ! modify res depending on symmetry
209  if (sym) then
210  ! set local lim_sec_X
211  lim_sec_x_loc(:,1) = [1,n_mod_x]
212  lim_sec_x_loc(:,2) = [1,n_mod_x]
213  if (present(lim_sec_x)) lim_sec_x_loc = lim_sec_x
214 
215  ! set res
216  if (lim_sec_x_loc(1,1)+sec_x_id(1).lt.&
217  &lim_sec_x_loc(1,2)+sec_x_id(2)) res = .false.
218  end if
219  end function is_necessary_x
220 
235  integer function calc_memory_x(ord,arr_size,n_mod,mem_size) result(ierr)
236  use iso_c_binding
237 
238  character(*), parameter :: rout_name = 'calc_memory_X'
239 
240  ! input / output
241  integer, intent(in) :: ord
242  integer, intent(in) :: arr_size
243  integer, intent(in) :: n_mod
244  real(dp), intent(inout) :: mem_size
245 
246  ! local variables
247  integer(C_SIZE_T) :: dp_size ! size of dp
248  character(len=max_str_ln) :: err_msg ! error message
249 
250  ! initialize ierr
251  ierr = 0
252 
253  call lvl_ud(1)
254 
255  ! get size of complex variable
256  dp_size = 2*sizeof(1._dp) ! complex variable
257 
258  ! calculate memory depending on order
259  select case(ord)
260  case (1) ! vectorial data: U, DU
261  ! set memory size
262  mem_size = 4*arr_size
263  mem_size = mem_size*n_mod**ord
264  mem_size = mem_size*dp_size
265  case (2) ! tensorial data: PV, KV
266  ! set memory size
267  mem_size = arr_size
268  mem_size = mem_size*(2*n_mod**ord+4*n_mod*(n_mod+1)/2)
269  mem_size = mem_size*dp_size
270  case default
271  ierr = 1
272  err_msg = 'Orders > 2 are not implemented'
273  chckerr(err_msg)
274  end select
275 
276  ! convert B to MB
277  mem_size = mem_size*1.e-6_dp
278 
279  ! apply 50% safety factor (empirical)
280  mem_size = mem_size*1.5_dp
281 
282  ! test overflow
283  if (mem_size.lt.0) then
284  ierr = 1
285  chckerr('Overflow occured')
286  end if
287 
288  call lvl_ud(-1)
289  end function calc_memory_x
290 
292  integer function trim_modes(mds_i,mds_o,id_lim_i,id_lim_o) result(ierr)
293  use x_vars, only: modes_type
294 
295  character(*), parameter :: rout_name = 'trim_modes'
296 
297  ! input / output
298  type(modes_type), intent(in) :: mds_i
299  type(modes_type), intent(in) :: mds_o
300  integer, intent(inout) :: id_lim_i(2)
301  integer, intent(inout) :: id_lim_o(2)
302 
303  ! local variables
304  integer :: m ! counter
305  character(len=max_str_ln) :: err_msg ! error message
306 
307  ! initialize ierr
308  ierr = 0
309 
310  ! find limits point where input modes and output modes coincide
311  ! (input grid should comprise output grid)
312  id_lim_o = [1,size(mds_o%sec,1)]
313  id_lim_i = [-1,-1]
314  do m = 1,size(mds_i%sec,1)
315  if (mds_i%sec(m,1).eq.mds_o%sec(id_lim_o(1),1)) then
316  id_lim_i(1) = m
317  exit
318  end if
319  end do
320  do m = size(mds_i%sec,1),1,-1
321  if (mds_i%sec(m,1).eq.mds_o%sec(id_lim_o(2),1)) then
322  id_lim_i(2) = m
323  exit
324  end if
325  end do
326 
327  ! test
328  if (any(id_lim_o.le.0)) then
329  ierr = 1
330  err_msg = 'Cannot find limits of input modes'
331  chckerr(err_msg)
332  end if
333  end function trim_modes
334 end module x_utilities
num_utilities::c
integer function, public c(ij, sym, n, lim_n)
Convert 2-D coordinates (i,j) to the storage convention used in matrices.
Definition: num_utilities.f90:2556
num_vars::max_name_ln
integer, parameter, public max_name_ln
maximum length of filenames
Definition: num_vars.f90:51
x_utilities::get_sec_x_range
subroutine, public get_sec_x_range(sec_X_range_loc, sec_X_range_tot, m, sym, lim_sec_X)
Gets one of the the local ranges of contiguous tensorial perturbation variables to be printed or read...
Definition: X_utilities.f90:128
num_vars::dp
integer, parameter, public dp
double precision
Definition: num_vars.f90:46
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
x_utilities::sec_ind_loc2tot
Returns the sec_ind_tot used to refer to a perturbation quantity.
Definition: X_utilities.f90:22
x_utilities::is_necessary_x
logical function, public is_necessary_x(sym, sec_X_id, lim_sec_X)
Determines whether a variable needs to be considered:
Definition: X_utilities.f90:197
num_vars::iu
complex(dp), parameter, public iu
complex unit
Definition: num_vars.f90:85
num_vars::x_job_nr
integer, public x_job_nr
nr. of X job
Definition: num_vars.f90:78
str_utilities
Operations on strings.
Definition: str_utilities.f90:4
grid_vars::grid_type
Type for grids.
Definition: grid_vars.f90:59
x_vars
Variables pertaining to the perturbation quantities.
Definition: X_vars.f90:4
x_utilities::do_x
logical function, public do_x()
Tests whether this perturbatino job should be done.
Definition: X_utilities.f90:179
x_utilities
Numerical utilities related to perturbation operations.
Definition: X_utilities.f90:4
x_vars::modes_type
mode number type
Definition: X_vars.f90:36
num_utilities
Numerical utilities.
Definition: num_utilities.f90:4
messages
Numerical utilities related to giving output.
Definition: messages.f90:4
grid_vars
Variables pertaining to the different grids used.
Definition: grid_vars.f90:4
messages::lvl_ud
subroutine, public lvl_ud(inc)
Increases/decreases lvl of output.
Definition: messages.f90:254
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
x_utilities::calc_memory_x
integer function, public calc_memory_x(ord, arr_size, n_mod, mem_size)
Calculate memory in MB necessary for X variables.
Definition: X_utilities.f90:236
x_utilities::trim_modes
integer function, public trim_modes(mds_i, mds_o, id_lim_i, id_lim_o)
Limit input mode range to output mode range.
Definition: X_utilities.f90:293
num_vars::x_jobs_lims
integer, dimension(:,:), allocatable, public x_jobs_lims
data about X jobs: [ , , , ] for all jobs
Definition: num_vars.f90:76