PB3D  [2.45]
Ideal linear high-n MHD stability in 3-D
X_vars.f90
Go to the documentation of this file.
1 !------------------------------------------------------------------------------!
3 !------------------------------------------------------------------------------!
4 module x_vars
5 #include <PB3D_macros.h>
6  use str_utilities
7  use messages
8  use num_vars, only: dp, max_name_ln, iu, weight_dp
9  use grid_vars, only: grid_type
10 
11  implicit none
12 
13  private
14  public set_nm_x, set_nn_mod, &
17 #if ldebug
19 #endif
20 
36  type, public :: modes_type
37  integer, allocatable :: n(:,:)
38  integer, allocatable :: m(:,:)
39  integer, allocatable :: sec(:,:)
40  contains
42  procedure :: dealloc => dealloc_mds
43  end type
44 
51  type, public :: x_1_type
52  integer :: n_mod
53  integer :: lim_sec_x(2)
54  integer, allocatable :: n(:,:)
55  integer, allocatable :: m(:,:)
56  complex(dp), allocatable :: u_0(:,:,:,:)
57  complex(dp), allocatable :: u_1(:,:,:,:)
58  complex(dp), allocatable :: du_0(:,:,:,:)
59  complex(dp), allocatable :: du_1(:,:,:,:)
60 #if ldebug
61  real(dp) :: estim_mem_usage
62 #endif
63  contains
65  procedure :: init => init_x_1
67  procedure :: copy => copy_x_1
69  procedure :: dealloc => dealloc_x_1
70  end type
71 
81  type, public :: x_2_type
82  integer :: n_mod(2)
83  integer :: lim_sec_x(2,2)
84  integer, allocatable :: n_1(:,:)
85  integer, allocatable :: n_2(:,:)
86  integer, allocatable :: m_1(:,:)
87  integer, allocatable :: m_2(:,:)
88  complex(dp), allocatable :: pv_0(:,:,:,:)
89  complex(dp), allocatable :: pv_1(:,:,:,:)
90  complex(dp), allocatable :: pv_2(:,:,:,:)
91  complex(dp), allocatable :: kv_0(:,:,:,:)
92  complex(dp), allocatable :: kv_1(:,:,:,:)
93  complex(dp), allocatable :: kv_2(:,:,:,:)
94 #if ldebug
95  real(dp) :: estim_mem_usage
96 #endif
97  contains
99  procedure :: init => init_x_2
101  procedure :: copy => copy_x_2
103  procedure :: dealloc => dealloc_x_2
104  end type
105 
106  ! interfaces
107 
116  interface set_nm_x
118  module procedure set_nm_x_1
120  module procedure set_nm_x_2
121  end interface
122 
123  ! global variables
124  type(modes_type) :: mds_x
126  integer :: prim_x
127  integer :: min_sec_x
128  integer :: max_sec_x
129  integer :: n_mod_x
130  integer :: min_nm_x = 5
131  integer, allocatable :: min_n_x(:)
132  integer, allocatable :: max_n_x(:)
133  integer, allocatable :: min_m_x(:)
134  integer, allocatable :: max_m_x(:)
135  real(dp) :: min_r_sol
136  real(dp) :: max_r_sol
137 #if ldebug
138  integer :: n_alloc_x_1s
139  integer :: n_alloc_x_2s
140 #endif
141 
142 contains
144  subroutine set_nm_x_1(mds,grid_X,lim_sec_X_o,n_X_loc,m_X_loc,lim_sec_X_i)
145 
146  ! input / output
147  type(modes_type), intent(in) :: mds
148  type(grid_type), intent(in) :: grid_X
149  integer, intent(inout) :: lim_sec_X_o(2)
150  integer, intent(inout), allocatable :: n_X_loc(:,:)
151  integer, intent(inout), allocatable :: m_X_loc(:,:)
152  integer, intent(in), optional :: lim_sec_X_i(2)
153 
154  ! set output lim_sec_X
155  lim_sec_x_o = [1,n_mod_x]
156  if (present(lim_sec_x_i)) lim_sec_x_o = lim_sec_x_i
157 
158  ! set n and m
159  allocate(n_x_loc(grid_x%loc_n_r,lim_sec_x_o(2)-lim_sec_x_o(1)+1))
160  allocate(m_x_loc(grid_x%loc_n_r,lim_sec_x_o(2)-lim_sec_x_o(1)+1))
161  n_x_loc = mds%n(grid_x%i_min:grid_x%i_max,&
162  &lim_sec_x_o(1):lim_sec_x_o(2))
163  m_x_loc = mds%m(grid_x%i_min:grid_x%i_max,&
164  &lim_sec_x_o(1):lim_sec_x_o(2))
165  end subroutine set_nm_x_1
167  subroutine set_nm_x_2(mds,grid_X,lim_sec_X_o,n_X_1,m_X_1,n_X_2,m_X_2,&
168  &lim_sec_X_i)
169 
170  ! input / output
171  type(modes_type), intent(in) :: mds
172  type(grid_type), intent(in) :: grid_X
173  integer, intent(inout) :: lim_sec_X_o(2,2)
174  integer, intent(inout), allocatable :: n_X_1(:,:)
175  integer, intent(inout), allocatable :: m_X_1(:,:)
176  integer, intent(inout), allocatable :: n_X_2(:,:)
177  integer, intent(inout), allocatable :: m_X_2(:,:)
178  integer, intent(in), optional :: lim_sec_X_i(2,2)
179 
180  ! call vectorial version
181  if (present(lim_sec_x_i)) then
182  call set_nm_x(mds,grid_x,lim_sec_x_o(:,1),n_x_1,m_x_1,&
183  &lim_sec_x_i(:,1))
184  call set_nm_x(mds,grid_x,lim_sec_x_o(:,2),n_x_2,m_x_2,&
185  &lim_sec_x_i(:,2))
186  else
187  call set_nm_x(mds,grid_x,lim_sec_x_o(:,1),n_x_1,m_x_1)
188  call set_nm_x(mds,grid_x,lim_sec_x_o(:,2),n_x_2,m_x_2)
189  end if
190  end subroutine set_nm_x_2
191 
203  subroutine init_x_1(X,mds,grid_X,lim_sec_X)
204 #if ldebug
205  use num_vars, only: print_mem_usage, rank
206 #endif
207 
208  ! input / output
209  class(x_1_type), intent(inout) :: X
210  type(modes_type), intent(in) :: mds
211  type(grid_type), intent(in) :: grid_X
212  integer, intent(in), optional :: lim_sec_X(2)
213 
214  ! local variables
215  integer :: loc_n_r ! local nr. of normal points
216  integer :: n_par, n_geo ! tot. nr. of angular points in parallel and geodesic direction
217 
218  ! set local variables
219  loc_n_r = grid_x%loc_n_r
220  n_par = grid_x%n(1)
221  n_geo = grid_x%n(2)
222 
223 #if ldebug
224  ! initialize memory usage
225  if (print_mem_usage) x%estim_mem_usage = 0._dp
226 #endif
227 
228  ! set mode numbers
229  call set_nm_x(mds,grid_x,x%lim_sec_X,x%n,x%m,lim_sec_x)
230 
231  ! set n_mod
232  x%n_mod = size(x%n,2)
233 
234  ! allocate U_0
235  allocate(x%U_0(n_par,n_geo,loc_n_r,x%n_mod))
236 
237  ! allocate U_1
238  allocate(x%U_1(n_par,n_geo,loc_n_r,x%n_mod))
239 
240  ! allocate DU_0
241  allocate(x%DU_0(n_par,n_geo,loc_n_r,x%n_mod))
242 
243  ! allocate DU_1
244  allocate(x%DU_1(n_par,n_geo,loc_n_r,x%n_mod))
245 
246 #if ldebug
247  ! set estimated memory usage
248  if (print_mem_usage) x%estim_mem_usage = x%estim_mem_usage + &
249  &(n_par*n_geo*loc_n_r)*(x%n_mod*4)
250 
251  ! increment n_alloc_X_1s
253 
254  ! print memory usage
255  if (print_mem_usage) call writo('[rank '//trim(i2str(rank))//&
256  &' - Expected memory usage of X_1: '//&
257  &trim(r2strt(x%estim_mem_usage*weight_dp*2))//' kB]',alert=.true.)
258 #endif
259  end subroutine init_x_1
270  subroutine init_x_2(X,mds,grid_X,lim_sec_X,is_field_averaged)
271 #if ldebug
272  use num_vars, only: print_mem_usage, rank
273 #endif
274 
275  ! input / output
276  class(x_2_type), intent(inout) :: X
277  type(modes_type), intent(in) :: mds
278  type(grid_type), intent(in) :: grid_X
279  integer, intent(in), optional :: lim_sec_X(2,2)
280  logical, intent(in), optional :: is_field_averaged
281 
282  ! local variables
283  integer :: loc_n_r ! local nr. of normal points
284  integer :: n_par, n_geo ! tot. nr. of angular points in parallel and geodesic direction
285  integer :: nn_mod ! either n_mod^2, n_mod*(n_mod+1)/2 or 0
286 
287  ! set local variables
288  n_par = grid_x%n(1)
289  if (present(is_field_averaged)) then
290  if (is_field_averaged) n_par = 1
291  end if
292  n_geo = grid_x%n(2)
293  loc_n_r = grid_x%loc_n_r
294 
295 #if ldebug
296  ! initialize memory usage
297  if (print_mem_usage) x%estim_mem_usage = 0._dp
298 #endif
299 
300  ! set mode numbers
301  call set_nm_x(mds,grid_x,x%lim_sec_X,x%n_1,x%m_1,x%n_2,x%m_2,lim_sec_x)
302 
303  ! set n_mod
304  x%n_mod(1) = size(x%n_1,2)
305  x%n_mod(2) = size(x%n_2,2)
306 
307  ! set nnmod for symmetric quantities
308  nn_mod = set_nn_mod(.true.,lim_sec_x)
309 
310  ! allocate PV_i
311  allocate(x%PV_0(n_par,n_geo,loc_n_r,nn_mod)) ! symmetric
312  allocate(x%PV_1(n_par,n_geo,loc_n_r,product(x%n_mod))) ! not symmetric
313  allocate(x%PV_2(n_par,n_geo,loc_n_r,nn_mod)) ! symmetric
314 
315  ! allocate KV_i
316  allocate(x%KV_0(n_par,n_geo,loc_n_r,nn_mod)) ! symmetric
317  allocate(x%KV_1(n_par,n_geo,loc_n_r,product(x%n_mod))) ! not symmetric
318  allocate(x%KV_2(n_par,n_geo,loc_n_r,nn_mod)) ! symmetric
319 
320 #if ldebug
321  ! set estimated memory usage
322  if (print_mem_usage) x%estim_mem_usage = &
323  &x%estim_mem_usage + (n_par*n_geo*loc_n_r)*&
324  &(nn_mod*4+product(x%n_mod)*2) + product(x%n_mod)
325 
326  ! increment n_alloc_X_2s
328 
329  ! print memory usage
330  if (print_mem_usage) call writo('[rank '//trim(i2str(rank))//&
331  &' - Expected memory usage of X_2: '//&
332  &trim(r2strt(x%estim_mem_usage*weight_dp*2))//' kB]',alert=.true.)
333 #endif
334  end subroutine init_x_2
335 
337  subroutine copy_x_1(X_i,mds,grid_i,X_o)
338  use grid_vars, only: grid_type
339 
340  ! input / output
341  class(x_1_type), intent(in) :: X_i
342  type(modes_type), intent(in) :: mds
343  type(grid_type), intent(in) :: grid_i
344  type(x_1_type), intent(inout) :: X_o
345 
346  call x_o%init(mds,grid_i,lim_sec_x=x_i%lim_sec_X)
347 
348  ! U_i
349  x_o%U_0 = x_i%U_0
350  x_o%U_1 = x_i%U_1
351 
352  ! DU_i
353  x_o%DU_0 = x_i%DU_0
354  x_o%DU_1 = x_i%DU_1
355  end subroutine copy_x_1
356 
358  subroutine copy_x_2(X_i,mds,grid_i,X_o)
359  use grid_vars, only: grid_type
360 
361  ! input / output
362  class(x_2_type), intent(in) :: X_i
363  type(modes_type), intent(in) :: mds
364  type(grid_type), intent(in) :: grid_i
365  type(x_2_type), intent(inout) :: X_o
366 
367  call x_o%init(mds,grid_i,lim_sec_x=x_i%lim_sec_X,&
368  &is_field_averaged=size(x_i%PV_0,1).eq.1)
369 
370  ! PV_i
371  x_o%PV_0 = x_i%PV_0
372  x_o%PV_1 = x_i%PV_1
373  x_o%PV_2 = x_i%PV_2
374 
375  ! KV_i
376  x_o%KV_0 = x_i%KV_0
377  x_o%KV_1 = x_i%KV_1
378  x_o%KV_2 = x_i%KV_2
379  end subroutine copy_x_2
380 
382  integer function set_nn_mod(sym,lim_sec_X) result(nn_mod)
383  ! input / output
384  logical, intent(in) :: sym
385  integer, intent(in), optional :: lim_sec_x(2,2)
386 
387  ! local variables
388  integer :: id, jd ! counters
389  integer :: lim_sec_x_loc(2,2) ! local version of lim_sec_X
390 
391  ! set local lim_sec_X
392  lim_sec_x_loc(:,1) = [1,n_mod_x]
393  lim_sec_x_loc(:,2) = [1,n_mod_x]
394  if (present(lim_sec_x)) lim_sec_x_loc = lim_sec_x
395 
396  if (sym) then
397  ! set nnmod for symmetric quantities: discard indices above diagonal
398  nn_mod = 0
399  do jd = lim_sec_x_loc(1,2),lim_sec_x_loc(2,2)
400  do id = lim_sec_x_loc(1,1),lim_sec_x_loc(2,1)
401  if (id.ge.jd) nn_mod = nn_mod + 1
402  end do
403  end do
404  else
405  ! set nn_mod for asymmetric quantities: don't discard anything
406  nn_mod = product(lim_sec_x_loc(2,:)-lim_sec_x_loc(1,:)+1)
407  end if
408  end function set_nn_mod
409 
411  subroutine dealloc_mds(mds)
412  ! input / output
413  class(modes_type), intent(inout) :: mds
414 
415  ! deallocate allocatable variables
416  call dealloc_mds_final(mds)
417  contains
418  ! Note: intent(out) automatically deallocates the variable
420  subroutine dealloc_mds_final(mds)
421  ! input / output
422  type(modes_type), intent(out) :: mds ! modes variables to be deallocated
423  end subroutine dealloc_mds_final
424  end subroutine dealloc_mds
425 
427  subroutine dealloc_x_1(X)
428 #if ldebug
429  use num_vars, only: rank, print_mem_usage
430 #endif
431 
432  ! input / output
433  class(x_1_type), intent(inout) :: X
434 
435 #if ldebug
436  ! local variables
437  integer :: mem_diff ! difference in memory
438  real(dp) :: estim_mem_usage ! estimated memory usage
439 
440  ! memory usage before deallocation
441  if (print_mem_usage) then
442  mem_diff = get_mem_usage()
443  estim_mem_usage = x%estim_mem_usage
444  end if
445 #endif
446 
447  ! deallocate allocatable variables
448  call dealloc_x_1_final(x)
449 
450 #if ldebug
451  ! decrement n_alloc_X_1s
453 
454  ! memory usage difference after deallocation
455  if (print_mem_usage) then
456  mem_diff = mem_diff - get_mem_usage()
457  call writo('[Rank '//trim(i2str(rank))//' - liberated '//&
458  &trim(i2str(mem_diff))//'kB deallocating X_1 ('//&
459  &trim(i2str(nint(100*mem_diff/&
460  &(estim_mem_usage*weight_dp*2))))//&
461  &'% of estimated)]',alert=.true.)
462  end if
463 #endif
464  contains
465  ! Note: intent(out) automatically deallocates the variable
467  subroutine dealloc_x_1_final(X)
468  ! input / output
469  type(x_1_type), intent(out) :: X ! equilibrium to be deallocated
470  end subroutine dealloc_x_1_final
471  end subroutine dealloc_x_1
473  subroutine dealloc_x_2(X)
474 #if ldebug
475  use num_vars, only: rank, print_mem_usage
476 #endif
477 
478  ! input / output
479  class(x_2_type), intent(inout) :: X
480 
481 #if ldebug
482  ! local variables
483  integer :: mem_diff ! difference in memory
484  real(dp) :: estim_mem_usage ! estimated memory usage
485 
486  ! memory usage before deallocation
487  if (print_mem_usage) then
488  mem_diff = get_mem_usage()
489  estim_mem_usage = x%estim_mem_usage
490  end if
491 #endif
492 
493  ! deallocate allocatable variables
494  call dealloc_x_2_final(x)
495 
496 #if ldebug
497  ! decrement n_alloc_X_2s
499 
500  ! memory usage difference after deallocation
501  if (print_mem_usage) then
502  mem_diff = mem_diff - get_mem_usage()
503  call writo('[Rank '//trim(i2str(rank))//' - liberated '//&
504  &trim(i2str(mem_diff))//'kB deallocating X_2 ('//&
505  &trim(i2str(nint(100*mem_diff/&
506  &(estim_mem_usage*weight_dp*2))))//&
507  &'% of estimated)]',alert=.true.)
508  end if
509 #endif
510  contains
511  ! Note: intent(out) automatically deallocates the variable
513  subroutine dealloc_x_2_final(X)
514  ! input / output
515  type(x_2_type), intent(out) :: X ! equilibrium to be deallocated
516  end subroutine dealloc_x_2_final
517  end subroutine dealloc_x_2
518 end module x_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
num_vars
Numerical variables used by most other modules.
Definition: num_vars.f90:4
x_vars::mds_x
type(modes_type), public mds_x
modes variables for perturbation grid
Definition: X_vars.f90:124
x_vars::min_m_x
integer, dimension(:), allocatable, public min_m_x
lowest poloidal mode number m_X, in total eq grid
Definition: X_vars.f90:133
x_vars::dealloc_x_2
subroutine dealloc_x_2(X)
Deallocates tensorial perturbation variables.
Definition: X_vars.f90:474
str_utilities::i2str
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
Definition: str_utilities.f90:18
x_vars::min_r_sol
real(dp), public min_r_sol
min. normal range for pert.
Definition: X_vars.f90:135
messages::get_mem_usage
integer function, public get_mem_usage()
Returns the memory usage in kilobytes.
Definition: messages.f90:554
x_vars::copy_x_1
subroutine copy_x_1(X_i, mds, grid_i, X_o)
Deep copy of vectorial perturbation variables.
Definition: X_vars.f90:338
num_vars::iu
complex(dp), parameter, public iu
complex unit
Definition: num_vars.f90:85
str_utilities
Operations on strings.
Definition: str_utilities.f90:4
x_vars::min_sec_x
integer, public min_sec_x
m_X (pol. flux) or n_X (tor. flux) (only for X style 1)
Definition: X_vars.f90:127
grid_vars::grid_type
Type for grids.
Definition: grid_vars.f90:59
x_vars::set_nn_mod
integer function, public set_nn_mod(sym, lim_sec_X)
Sets number of entries for tensorial perturbation variables.
Definition: X_vars.f90:383
str_utilities::r2strt
elemental character(len=max_str_ln) function, public r2strt(k)
Convert a real (double) to string.
Definition: str_utilities.f90:54
x_vars::n_alloc_x_1s
integer, public n_alloc_x_1s
nr. of allocated X_1's
Definition: X_vars.f90:138
num_vars::weight_dp
real(dp), parameter, public weight_dp
size of double precision in kB
Definition: num_vars.f90:49
x_vars::copy_x_2
subroutine copy_x_2(X_i, mds, grid_i, X_o)
Deep copy of tensorial perturbation variables.
Definition: X_vars.f90:359
x_vars::init_x_2
subroutine init_x_2(X, mds, grid_X, lim_sec_X, is_field_averaged)
Initializes a tensorial perturbation.
Definition: X_vars.f90:271
x_vars::prim_x
integer, public prim_x
n_X (pol. flux) or m_X (tor. flux)
Definition: X_vars.f90:126
x_vars::max_r_sol
real(dp), public max_r_sol
max. normal range for pert.
Definition: X_vars.f90:136
x_vars::max_n_x
integer, dimension(:), allocatable, public max_n_x
highest poloidal mode number m_X, in total eq grid
Definition: X_vars.f90:132
x_vars::dealloc_mds
subroutine dealloc_mds(mds)
Deallocates modes variables.
Definition: X_vars.f90:412
x_vars::x_2_type
tensorial perturbation type
Definition: X_vars.f90:81
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
x_vars::modes_type
mode number type
Definition: X_vars.f90:36
x_vars::mds_sol
type(modes_type), public mds_sol
modes variables for solution grid
Definition: X_vars.f90:125
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
x_vars::init_x_1
subroutine init_x_1(X, mds, grid_X, lim_sec_X)
Initializes a vectorial perturbation.
Definition: X_vars.f90:204
x_vars::set_nm_x
Sets n_X and m_X.
Definition: X_vars.f90:116
x_vars::max_m_x
integer, dimension(:), allocatable, public max_m_x
highest poloidal mode number m_X, in total eq grid
Definition: X_vars.f90:134
x_vars::min_nm_x
integer, public min_nm_x
minimum for the high-n theory (debable)
Definition: X_vars.f90:130
grid_vars
Variables pertaining to the different grids used.
Definition: grid_vars.f90:4
x_vars::max_sec_x
integer, public max_sec_x
m_X (pol. flux) or n_X (tor. flux) (only for\ c X style 1)
Definition: X_vars.f90:128
x_vars::dealloc_x_1
subroutine dealloc_x_1(X)
Deallocates vectorial perturbation variables.
Definition: X_vars.f90:428
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_vars::n_alloc_x_2s
integer, public n_alloc_x_2s
nr. of allocated X_2's
Definition: X_vars.f90:139
x_vars::min_n_x
integer, dimension(:), allocatable, public min_n_x
lowest poloidal mode number m_X, in total eq grid
Definition: X_vars.f90:131
x_vars::x_1_type
vectorial perturbation type
Definition: X_vars.f90:51
num_vars::rank
integer, public rank
MPI rank.
Definition: num_vars.f90:68