PB3D [2.47]
Ideal linear high-n MHD stability in 3-D
Loading...
Searching...
No Matches
grid_vars.f90
Go to the documentation of this file.
1!------------------------------------------------------------------------------!
2!> Variables pertaining to the different grids used.
3!------------------------------------------------------------------------------!
5#include <PB3D_macros.h>
7 use messages
8 use num_vars, only: dp, pi, max_str_ln, weight_dp
9
10 implicit none
11 private
14#if ldebug
16#endif
17
18 ! global variables
19 integer :: n_r_in !< nr. of normal points in input grid
20 integer :: n_r_eq !< nr. of normal points in equilibrium grid
21 integer :: n_r_x !< nr. of normal points in perturbation grid
22 integer :: n_r_sol !< nr. of normal points in solution grid
23 integer :: n_alpha !< nr. of field-lines
24 real(dp) :: min_par_x !< min. of parallel coordinate [\f$\pi\f$] in field-aligned grid
25 real(dp) :: max_par_x !< max. of parallel coordinate [\f$\pi\f$] in field-aligned grid
26 real(dp) :: min_alpha !< min. of field-line label [\f$\pi\f$] in field-aligned grid
27 real(dp) :: max_alpha !< max. of field-line label [\f$\pi\f$] in field-aligned grid
28 real(dp), allocatable :: alpha(:) !< field line label alpha
29#if ldebug
30 integer :: n_alloc_grids !< nr. of allocated grids \ldebug
31 integer :: n_alloc_discs !< nr. of allocated discretizations \ldebug
32#endif
33
34 !> Type for grids
35 !!
36 !! The grids are saved in the following format:
37 !! <tt>(angle_1,angle_2,r)</tt>, where \c angle_1 and \c angle_2 can be any
38 !! angle that completely describe a flux surface.
39 !!
40 !! For example, they can refer to a grid of \f$\theta\f$ and \f$\zeta\f$
41 !! values, but they can also refer to (Modified) flux coordinates with a
42 !! parallel angle and a field line coordinate (\f$\alpha\f$).
43 !!
44 !! For field-aligned grids, \c angle_1 is generally chosen equal to the
45 !! parallel coordinate in the Flux coordinate system, and \c angle_2 equal
46 !! to the field line label (so the second dimension of the matrices is then
47 !! chosen to be of size 1 for the calculations on a single field line).
48 !!
49 !! At the same time, the parallel coordinate, in which integrations will
50 !! have to be done, ocupies the first index. This is good for numerical
51 !! efficiency.
52 !!
53 !! For specific equilibrium grids, such as the case for HELENA equilibria,
54 !! \c angle_1 corresponds to \f$\theta\f$ and \c angle_2 to the symmetry
55 !! angle \f$\zeta\f$.
56 !!
57 !! It is important that this order of the coordinates in space is consistent
58 !! among all the variables.
59 type, public :: grid_type
60 integer :: n(3) !< tot nr. of points
61 integer :: loc_n_r !< local nr. of normal points
62 integer :: i_min !< min. normal index of this process in full arrays
63 integer :: i_max !< max. normal index of this process in full arrays
64 logical :: divided !< whether the grid is split up among the processes
65 real(dp), pointer :: r_e(:) => null() !< E(quilibrium) coord. values at n points
66 real(dp), pointer :: r_f(:) => null() !< F(lux) coord. values at n points
67 real(dp), pointer :: loc_r_e(:) => null() !< E(quilibrium) coord. values at n points
68 real(dp), pointer :: loc_r_f(:) => null() !< F(lux) coord. values at n points
69 real(dp), pointer :: theta_e(:,:,:) => null() !< E(quilibrium) coord. values of first angle at n points in 3-D
70 real(dp), pointer :: theta_f(:,:,:) => null() !< F(lux) coord. values of first angle at n points in 3-D
71 real(dp), pointer :: zeta_e(:,:,:) => null() !< E(quilibrium) coord. values of second angle at n points in 3-D
72 real(dp), pointer :: zeta_f(:,:,:) => null() !< F(lux) coord. values of second angle at n points in 3-D
73 real(dp), allocatable :: trigon_factors(:,:,:,:,:) !< trigonometric factor cosine for the inverse fourier transf.
74#if ldebug
75 real(dp) :: estim_mem_usage !< estimated memory usage \ldebug
76#endif
77 contains
78 !> initialize
79 procedure :: init => init_grid
80 !> copy
81 procedure :: copy => copy_grid
82 !> deallocate
83 procedure :: dealloc => dealloc_grid
84 end type
85
86contains
87 !> \public Initializes a new grid.
88 !!
89 !! Optionally, the local limits can be provided for a divided grid.
90 !!
91 !! Optionally, it can be set whether the grid is divided or not. A situation
92 !! where this is useful is when only a subset of MPI processes is used to
93 !! calculate the solution in SLEPC. In this case, the extra ranks all only
94 !! contain the last grid point, and the last used process has as upper limit
95 !! this same grid point. This way, all the procedures are reusable, but in
96 !! this case if only one process is used, this procedure becomes confused
97 !! and sets this process to undivided. In most cases, this functionality
98 !! probably does not need to be used.
99 !!
100 !! \return ierr
101 integer function init_grid(grid,n,i_lim,divided) result(ierr)
102#if ldebug
103 use num_vars, only: print_mem_usage, rank
104#endif
105 character(*), parameter :: rout_name = 'init_grid'
106
107 ! input / output
108 class(grid_type), intent(inout) :: grid !< grid to be initialized
109 integer, intent(in) :: n(3) !< tot. nr. of points (par,r,alpha)
110 integer, intent(in), optional :: i_lim(2) !< min. and max. local normal index
111 logical, intent(in), optional :: divided !< divided grid or not
112
113 ! local variables
114 character(len=max_str_ln) :: err_msg ! error message
115 logical :: divided_loc ! local divided
116
117 ! initialize ierr
118 ierr = 0
119
120 ! tests
121 if (present(i_lim)) then
122 if (i_lim(2)-i_lim(1)+1.gt.n(3)) then
123 ierr = 1
124 err_msg = 'The local nr. of normal points cannot be higher &
125 &than the total nr. of normal points'
126 chckerr(err_msg)
127 end if
128 end if
129
130#if ldebug
131 ! initialize memory usage
132 if (print_mem_usage) grid%estim_mem_usage = 0._dp
133#endif
134
135 ! set local divided and loc_n_r
136 divided_loc = .false.
137 if (present(i_lim)) then ! might be divided grid
138 if (i_lim(2).lt.i_lim(1)) then
139 ierr = 1
140 write(*,*) 'i_lim = ', i_lim
141 err_msg = 'faulty i_lim'
142 chckerr(err_msg)
143 end if
144 grid%i_min = i_lim(1)
145 grid%i_max = i_lim(2)
146 grid%loc_n_r = i_lim(2)-i_lim(1)+1
147 if (i_lim(2)-i_lim(1)+1.lt.n(3)) divided_loc = .true. ! only divided if difference between local and total
148 else ! certainly not divided grid
149 grid%i_min = 1
150 grid%i_max = n(3)
151 grid%loc_n_r = n(3)
152 end if
153 if (present(divided)) divided_loc = divided
154
155 grid%divided = divided_loc
156
157 ! allocate normal variables
158 grid%n = n
159 allocate(grid%r_E(n(3)))
160 allocate(grid%r_F(n(3)))
161 if (divided_loc) then
162 allocate(grid%loc_r_E(grid%loc_n_r))
163 allocate(grid%loc_r_F(grid%loc_n_r))
164 else
165 grid%loc_r_E => grid%r_E
166 grid%loc_r_F => grid%r_F
167 end if
168
169#if ldebug
170 ! set estimated memory usage
171 if (print_mem_usage) grid%estim_mem_usage = grid%estim_mem_usage + &
172 &grid%n(3)*2
173#endif
174
175 ! allocate angular variables
176 if (n(1).ne.0 .and. n(2).ne.0) then
177 allocate(grid%theta_E(n(1),n(2),grid%loc_n_r))
178 allocate(grid%zeta_E(n(1),n(2),grid%loc_n_r))
179 allocate(grid%theta_F(n(1),n(2),grid%loc_n_r))
180 allocate(grid%zeta_F(n(1),n(2),grid%loc_n_r))
181
182#if ldebug
183 ! set estimated memory usage
184 if (print_mem_usage) grid%estim_mem_usage = grid%estim_mem_usage + &
185 &grid%loc_n_r*n(1)*n(2)*4
186#endif
187 end if
188
189#if ldebug
190 ! increment n_alloc_grids
192
193 ! print memory usage
194 if (print_mem_usage) call writo('[rank '//trim(i2str(rank))//&
195 &' - Expected memory usage of grid: '//&
196 &trim(r2strt(grid%estim_mem_usage*weight_dp))//' kB]',&
197 &alert=.true.)
198#endif
199 end function init_grid
200
201 !> \public Deallocates a grid.
202 subroutine dealloc_grid(grid)
203#if ldebug
204 use num_vars, only: rank, print_mem_usage
205#endif
206 ! input / output
207 class(grid_type), intent(inout) :: grid !< grid to be deallocated
208
209 ! local variables
210#if ldebug
211 integer :: mem_diff ! difference in memory
212 real(dp) :: estim_mem_usage ! estimated memory usage
213
214 ! memory usage before deallocation
215 if (print_mem_usage) then
216 mem_diff = get_mem_usage()
217 estim_mem_usage = grid%estim_mem_usage
218 end if
219#endif
220
221 ! deallocate allocated pointers
222 deallocate(grid%r_E,grid%r_F)
223 if (grid%n(1).ne.0 .and. grid%n(2).ne.0) then ! 3D grid
224 deallocate(grid%theta_E,grid%zeta_E)
225 deallocate(grid%theta_F,grid%zeta_F)
226 end if
227 if (grid%divided) deallocate(grid%loc_r_E,grid%loc_r_F)
228
229 ! nullify pointers
230 nullify(grid%r_E,grid%r_F)
231 nullify(grid%theta_E,grid%zeta_E)
232 nullify(grid%theta_F,grid%zeta_F)
233 nullify(grid%loc_r_E,grid%loc_r_F)
234
235 ! deallocate allocatable variables
236 call dealloc_grid_final(grid)
237
238#if ldebug
239 ! decrement n_alloc_grids
241
242 ! memory usage difference after deallocation
243 if (print_mem_usage) then
244 mem_diff = mem_diff - get_mem_usage()
245 call writo('[Rank '//trim(i2str(rank))//' - liberated '//&
246 &trim(i2str(mem_diff))//'kB deallocating grid ('//&
247 &trim(i2str(nint(100*mem_diff/&
248 &(estim_mem_usage*weight_dp))))//&
249 &'% of estimated)]',alert=.true.)
250 end if
251#endif
252 contains
253 ! Note: intent(out) automatically deallocates the variable
254 !> \private
255 subroutine dealloc_grid_final(grid)
256 ! input / output
257 type(grid_type), intent(out) :: grid ! grid to be deallocated
258 end subroutine dealloc_grid_final
259 end subroutine dealloc_grid
260
261 !> \public Deep copy of a grid.
262 !!
263 !! \note Does not copy possible trigoniometric factors.
264 !!
265 !! \return ierr
266 integer function copy_grid(grid_i,grid_o) result(ierr)
267 character(*), parameter :: rout_name = 'copy_grid'
268
269 ! input / output
270 class(grid_type), intent(in) :: grid_i !< grid to be copied
271 type(grid_type), intent(inout) :: grid_o !< copied grid
272
273 ! initialize ierr
274 ierr = 0
275
276 ierr = init_grid(grid_o,grid_i%n,i_lim=[grid_i%i_min,grid_i%i_max],&
277 &divided=grid_i%divided)
278 chckerr('')
279 grid_o%r_E = grid_i%r_E
280 grid_o%r_F = grid_i%r_F
281 grid_o%loc_r_E = grid_i%loc_r_E
282 grid_o%loc_r_F = grid_i%loc_r_F
283 if (associated(grid_i%theta_E)) grid_o%theta_E = grid_i%theta_E
284 if (associated(grid_i%theta_F)) grid_o%theta_F = grid_i%theta_F
285 if (associated(grid_i%zeta_E)) grid_o%zeta_E = grid_i%zeta_E
286 if (associated(grid_i%zeta_F)) grid_o%zeta_F = grid_i%zeta_F
287 if (allocated(grid_i%trigon_factors)) then
288 allocate(grid_o%trigon_factors(size(grid_i%trigon_factors,1),&
289 &size(grid_i%trigon_factors,2),size(grid_i%trigon_factors,3),&
290 &size(grid_i%trigon_factors,4),size(grid_i%trigon_factors,5)))
291 grid_o%trigon_factors = grid_i%trigon_factors
292 end if
293 end function copy_grid
294end module grid_vars
Variables pertaining to the different grids used.
Definition grid_vars.f90:4
real(dp), dimension(:), allocatable, public alpha
field line label alpha
Definition grid_vars.f90:28
integer, public n_alloc_discs
nr. of allocated discretizations
Definition grid_vars.f90:31
real(dp), public min_par_x
min. of parallel coordinate [ ] in field-aligned grid
Definition grid_vars.f90:24
integer function copy_grid(grid_i, grid_o)
Deep copy of a grid.
integer, public n_alpha
nr. of field-lines
Definition grid_vars.f90:23
integer function init_grid(grid, n, i_lim, divided)
Initializes a new grid.
integer, public n_r_eq
nr. of normal points in equilibrium grid
Definition grid_vars.f90:20
subroutine dealloc_grid(grid)
Deallocates a grid.
integer, public n_r_x
nr. of normal points in perturbation grid
Definition grid_vars.f90:21
integer, public n_alloc_grids
nr. of allocated grids
Definition grid_vars.f90:30
real(dp), public max_par_x
max. of parallel coordinate [ ] in field-aligned grid
Definition grid_vars.f90:25
integer, public n_r_in
nr. of normal points in input grid
Definition grid_vars.f90:19
real(dp), public max_alpha
max. of field-line label [ ] in field-aligned grid
Definition grid_vars.f90:27
real(dp), public min_alpha
min. of field-line label [ ] in field-aligned grid
Definition grid_vars.f90:26
integer, public n_r_sol
nr. of normal points in solution grid
Definition grid_vars.f90:22
Numerical utilities related to giving output.
Definition messages.f90:4
integer function, public get_mem_usage()
Returns the memory usage in kilobytes.
Definition messages.f90:554
subroutine, public writo(input_str, persistent, error, warning, alert)
Write output to file identified by output_i.
Definition messages.f90:275
Numerical variables used by most other modules.
Definition num_vars.f90:4
integer, parameter, public dp
double precision
Definition num_vars.f90:46
real(dp), parameter, public pi
Definition num_vars.f90:83
logical, public print_mem_usage
print memory usage is printed
Definition num_vars.f90:149
integer, parameter, public max_str_ln
maximum length of strings
Definition num_vars.f90:50
integer, public rank
MPI rank.
Definition num_vars.f90:68
real(dp), parameter, public weight_dp
size of double precision in kB
Definition num_vars.f90:49
Operations on strings.
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
elemental character(len=max_str_ln) function, public r2strt(k)
Convert a real (double) to string.
Type for grids.
Definition grid_vars.f90:59