• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gyrokinetics / gs2 / 2021218321

04 Sep 2025 07:44AM UTC coverage: 10.606% (+0.03%) from 10.577%
2021218321

push

gitlab-ci

David Dickinson
Merged in feature/move_more_initialisation_to_init_levels (pull request #1161)

4710 of 44407 relevant lines covered (10.61%)

125698.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

34.34
/src/gs2_init.fpp
1
! This file is used alongside code generated by generate_gs2_init.py
2

3
!> This module is analogous to the init() function
4
!> in Linux-based operating systems: it initialises
5
!> gs2 to a certain init_level. At a given init level,
6
!> certain modules are initialised and certain are not.
7
!>
8
!> The gs2_init module is used by gs2_main to initialise modules. A typical
9
!> additional use case for this module is when it is desired
10
!> to override a given parameter (as in the override_* functions
11
!> in gs2_main). GS2 must be taken down to the appropriate
12
!> init_level, where all modules which contain any of those
13
!> parameters are uninitialized. The override is then set
14
!> and gs2 is brought back up to the highest init_level.
15
!>
16
!> As in Linux, this module cannot be used until a certain
17
!> basic initialization has happened (think loading the kernel).
18
!> This basic initialization occurs in gs2_initialize in gs2_main,
19
!> and set the init_level to gs2_initialized.
20
!>
21
!> This is free software released under the MIT licence.
22
!> Originally written by:
23
!>            Edmund Highcock (edmundhighcock@users.sourceforge.net)
24
module gs2_init
25
  use abstract_config, only: abstract_config_type, CONFIG_MAX_NAME_LEN
26
  use overrides, only: initial_values_overrides_type, optimisations_overrides_type
27
  use config_collection, only: gs2_config_type
28
  implicit none
29

30
  private
31

32
  public :: init_type
33

34
  !> A list of possible intialization levels.
35
  public :: init_level_list
36

37
  !> Bring gs2 to the target initialization level.
38
  public :: init
39

40
  !> Reads the gs2_init namelist
41
  public :: init_gs2_init
42

43
  !> Finalize the module
44
  public :: finish_gs2_init
45

46
  public :: write_init_times, report_init_times, reset_init_times
47

48
  !> A type for storing the current initialization
49
  !> status, as well as all the overrides.
50
  type init_type
51
     !> The current init level
52
     integer :: level = 0
53
     !> An object for overriding the initial values of
54
     !> the fields and distribution function. You must call
55
     !> gs2_main::prepare_initial_values_overrides
56
     !> before setting these overrides. This override
57
     !> is very complicated. See
58
     !> documentation for the overrides::initial_values_overrides_type
59
     !> for more information.
60
     type(initial_values_overrides_type) :: initval_ov
61
     !> An object for overriding non physics parameters which
62
     !> may alter run time and efficiency. You must call
63
     !> gs2_main::prepare_optimisations_overrides
64
     !> before setting these overrides.
65
     type(optimisations_overrides_type) :: opt_ov
66
     !> A config collection instance which can be used to override
67
     !> defaults, skip reading certain configs etc.
68
     type(gs2_config_type) :: config
69
   contains
70
     procedure, private :: init_pass_int_bound, init_pass_type_bound
71
     generic :: init => init_pass_int_bound, init_pass_type_bound
72
  end type init_type
73

74
  !> Define an type to represent an initialisation level.
75
  !> This uses a hack to approximate type extension without
76
  !> the boiler plate of extending an abstract type.
77
  !> Specifically, we offer a type bound change_level procedure
78
  !> which just calls a procedure pointer to implement the
79
  !> actual work to change the level, specific to each instance.
80
  type :: init_level_type
81
     character(len=40) :: name = 'init level name not set'
82
     integer :: level = -1
83
     !> Used to set the verbosity level at which this
84
     !> level reports debug messages.
85
     integer :: debug_message_level = 1
86
     procedure(change_level_specific_interface), pointer, nopass, private :: change_level_specific => null()
87
     real, dimension(2) :: time_init = 0.
88
   contains
89
     procedure :: generate_debug_message => init_level_generate_debug_message
90
     procedure :: report_time => init_level_report_time
91
     procedure :: change_level => init_level_change_level
92
  end type init_level_type
93

94
  interface
95
     subroutine change_level_specific_interface(current, going_up)
96
       import init_type
97
       implicit none
98
       type(init_type), intent(in out) :: current
99
       logical, intent(in) :: going_up
100
     end subroutine change_level_specific_interface
101
  end interface
102

103
  !> Used to store all the init_level_type instances. Setup during
104
  !> init_gs2_init.
105
  type(init_level_type), dimension(:), allocatable :: init_levels
106

107
  !> A type for labelling the different init
108
  !> levels available in gs2.
109
  type init_level_list_type
110
#include "gs2_init_level_list.inc"
111
  end type init_level_list_type
112

113
  type(init_level_list_type), parameter :: init_level_list = init_level_list_type()
114

115
  logical :: initialized = .false.
116

117
  interface init
118
     module procedure :: init_pass_type
119
     module procedure :: init_pass_int
120
  end interface init
121

122
contains
123

124
  !> Produce the debug message associated with this level
125
  subroutine init_level_generate_debug_message(self, going_up)
552✔
126
    use unit_tests, only: debug_message
127
    implicit none
128
    class(init_level_type), intent(in) :: self
129
    logical, intent(in) :: going_up
130
    character(len=:), allocatable :: direction_msg
552✔
131
    character(len=3) :: level_as_string
132
    if (going_up) then
552✔
133
       direction_msg = 'up'
276✔
134
    else
135
       direction_msg = 'down'
276✔
136
    end if
137
    write(level_as_string , '(I0)') self%level
552✔
138
    call debug_message(self%debug_message_level, &
139
         'gs2_init:init '//direction_msg//' reached init level -- '// &
140
         trim(adjustl(self%name))//' ('//trim(level_as_string)//')')
552✔
141
  end subroutine init_level_generate_debug_message
552✔
142

143
  !> Report the time spent in init for this level
144
  subroutine init_level_report_time(self, unit)
×
145
    use iso_fortran_env, only: output_unit
146
    use optionals, only: get_option_with_default
147
    implicit none
148
    class(init_level_type), intent(in) :: self
149
    integer, intent(in), optional :: unit
150
    write(get_option_with_default(unit, output_unit), '(A," : ",0pf9.3," seconds")') &
151
         trim(adjustl(self%name)), self%time_init(1)
×
152
  end subroutine init_level_report_time
×
153

154
  !> General wrapper to the init_level instance's specific
155
  !> change level method.
156
  integer function init_level_change_level(self, current, going_up) result(new_level)
552✔
157
    use job_manage, only: time_message
158
    implicit none
159
    class(init_level_type), intent(in out) :: self
160
    type(init_type), intent(in out) :: current
161
    logical, intent(in) :: going_up
162
    call self%generate_debug_message(going_up)
552✔
163
    call time_message(.false., self%time_init, 'Init')
552✔
164
    call self%change_level_specific(current, going_up)
552✔
165
    call time_message(.false., self%time_init, 'Init')
552✔
166
    if (going_up) then
552✔
167
       new_level = self%level
276✔
168
    else
169
       new_level = self%level - 1
276✔
170
    end if
171
  end function init_level_change_level
552✔
172

173
  !> Write the init times to <run_name>.init_times
174
  subroutine write_init_times()
×
175
    use mp, only: proc0
176
    use file_utils, only: open_output_file, close_output_file
177
    implicit none
178
    integer :: unit
179
    if (.not. proc0) return
×
180
    call open_output_file(unit, '.init_times')
×
181
    call report_init_times(unit)
×
182
    call close_output_file(unit)
×
183
  end subroutine write_init_times
184

185
  !> Report the time spent in each initialisation level
186
  subroutine report_init_times(unit)
×
187
    implicit none
188
    integer, intent(in), optional :: unit
189
    integer :: ilevel
190
    do ilevel = 1, size(init_levels)
×
191
       call init_levels(ilevel)%report_time(unit)
×
192
    end do
193
  end subroutine report_init_times
×
194

195
  !> Reset the time spent in each initialisation level
196
  subroutine reset_init_times()
×
197
    implicit none
198
    init_levels%time_init(1) = 0.
×
199
    init_levels%time_init(2) = 0.
×
200
  end subroutine reset_init_times
×
201

202
  !> Small wrapper to allow init_level_type to be passed
203
  !> instead of the level integer.
204
  subroutine init_pass_type_bound(self, target_level)
×
205
    class(init_type), intent(inout) :: self
206
    type(init_level_type), intent(in) :: target_level
207
    call self%init(target_level%level)
×
208
  end subroutine init_pass_type_bound
×
209

210
  !> Initialize gs2 to the level of target_level.
211
  !> The init_type self contains info
212
  !> about the initialization level. At the end
213
  !> of the subroutine, self%level is set to target_level
214
  subroutine init_pass_int_bound(self, target_level)
108✔
215
    use fields, only: init_fields
216
    use mp, only: mp_abort
217
    implicit none
218
    class(init_type), intent(in out) :: self
219
    integer, intent(in) :: target_level
220
    logical :: going_up
221
    integer :: ilevel, offset
222
    if (self%level < init_level_list%basic) then
108✔
223
       call mp_abort("gs2_init::init cannot be called before &
224
            & initialize_gs2 in gs2 main", .true.)
×
225
    end if
226

227
    if (self%level == target_level) then
108✔
228
       return
8✔
229
    else
230
       going_up = self%level < target_level
100✔
231

232
       if (going_up) then
100✔
233
          offset = 1
64✔
234
       else
235
          offset = 0
36✔
236
       end if
237

238
       ! Written as a while loop in this way such that we are not sensitive to the
239
       ! order of entries in the init_levels array.
240
       do while (self%level /= target_level)
652✔
241
          ilevel = findloc(init_levels%level, self%level + offset, dim = 1)
3,576✔
242
          self%level = init_levels(ilevel)%change_level(self, going_up)
552✔
243
       end do
244
    end if
245
  end subroutine init_pass_int_bound
246

247
  subroutine init_pass_type(current, target_level)
×
248
    type(init_type), intent(in out) :: current
249
    type(init_level_type), intent(in) :: target_level
250
    call current%init(target_level)
×
251
  end subroutine init_pass_type
×
252

253
  subroutine init_pass_int(current, target_level)
108✔
254
    type(init_type), intent(in out) :: current
255
    integer , intent(in) :: target_level
256
    call current%init(target_level)
108✔
257
  end subroutine init_pass_int
108✔
258

259
#include "gs2_init_subroutines.inc"
260

261
  !> Initialise this module. As we pass in the initialisation state
262
  !> object (current), we could/should consider making this set the
263
  !> level to basic, e.g. current%level = init_level_list%basic
264
  subroutine init_gs2_init
6✔
265
    implicit none
266
    if (initialized) return
6✔
267
    initialized = .true.
2✔
268
#include "gs2_init_level_array.inc"
269
  end subroutine init_gs2_init
270

271
  !> Finish this module
272
  subroutine finish_gs2_init()
×
273
    use run_parameters, only: save_init_times
274
    implicit none
275
    if (save_init_times) call write_init_times
×
276
    initialized = .false.
×
277
    if (allocated(init_levels)) deallocate(init_levels)
×
278
  end subroutine finish_gs2_init
×
279

280
  subroutine set_initial_field_and_dist_fn_values(current)
×
281
    use dist_fn_arrays, only: g, gnew, gexp_1, gexp_2, gexp_3
282
    use fields_arrays, only: phinew, aparnew, bparnew, phi, apar, bpar
283
    use fields, only: force_maxwell_reinit
284
    use fields, only: set_init_fields
285
    use file_utils, only: error_unit
286
    use gs2_save, only: init_vnm
287
    use init_g, only: ginit, ginitopt_restart_many, initial_condition_is_nonadiabatic_dfn
288
    use run_parameters, only: has_phi, has_apar, has_bpar
289
    use collisions, only: set_vnmult
290
    use array_utils, only: copy, zero_array
291
    implicit none
292
    type (init_type), intent(in) :: current
293
    logical :: restarted
294
    real, dimension(2) :: new_vnmult
295
    if (.not. current%initval_ov%override) then
×
296
       ! This is the usual initial setup
297
       call ginit (restarted)
×
298
       ! If initial_condition_is_nonadiabatic_dfn then we have already
299
       ! calculated the correct fields, unless restarting, so return straight away.
300
       ! If restarting then we deal with this further below.
301
       if ((.not.restarted) .and. initial_condition_is_nonadiabatic_dfn) return
×
302
       ! If we're restarting from file then we don't want to recalculate
303
       ! the fields unless force_maxwell_reinit is true. If we are not
304
       ! restarting then we better call set_init_fields to set the initial
305
       ! fields here.
306
       if ((.not.restarted) .or. force_maxwell_reinit) call set_init_fields
×
307
       return
×
308
    else
309
       if (current%initval_ov%in_memory) then
×
310
          call copy(current%initval_ov%g, g)
×
311
          call copy(g, gnew)
×
312
          new_vnmult = current%initval_ov%vnmult
×
313
       else
314
          call ginit(restarted, ginitopt_restart_many)
×
315
          call init_vnm(new_vnmult)
×
316
       end if
317
       call set_vnmult(new_vnmult)
×
318
    end if
319

320
    if (current%initval_ov%in_memory) then
×
321
       if (allocated(current%initval_ov%gexp_1)) call copy(current%initval_ov%gexp_1, gexp_1)
×
322
       if (allocated(current%initval_ov%gexp_1)) call copy(current%initval_ov%gexp_2, gexp_2)
×
323
       if (allocated(current%initval_ov%gexp_1)) call copy(current%initval_ov%gexp_3, gexp_3)
×
324
    end if
325

326
    ! Do not use the value from state%init%initval_ov%force_maxwell_reinit = current%initval_ov%force_maxwell_reinit as follows:
327
    !     if (current%initval_ov%force_maxwell_reinit)then
328
    ! as was done previously because, when restarting a run, this part of the overrides system has not been initialised with the
329
    ! value from the input file yet. As a result, the above condition is always true, even if the restart file has
330
    ! force_maxwell_reinit = .false.! (For a reinitialisation due to a timestep change, this part of the override system would be
331
    ! set up correctly and the above condition would respect the value in the input file.) Unfortunately, because of the way the
332
    ! state object and the overrides system is set up, it is not possible to have this value correctly initialised from the input
333
    ! file by this point in a restarted run. Therefore, use the input file value directly to ensure we respect the value in the
334
    ! input file at the start of restarted runs.
335
    if (force_maxwell_reinit)then
×
336
       call set_init_fields
×
337
    else
338

339
       if(current%initval_ov%override .and. current%initval_ov%in_memory) then
×
340
          if(has_phi) then
×
341
             call copy(current%initval_ov%phi, phinew)
×
342
          else
343
             call zero_array(phinew)
×
344
          endif
345
          if(has_apar) then
×
346
             call copy(current%initval_ov%apar, aparnew)
×
347
          else
348
             call zero_array(aparnew)
×
349
          endif
350
          if(has_bpar) then
×
351
             call copy(current%initval_ov%bpar, bparnew)
×
352
          else
353
             call zero_array(bparnew)
×
354
          endif
355
          call copy(phinew, phi)
×
356
          call copy(aparnew, apar)
×
357
          call copy(bparnew, bpar)
×
358
       else
359
          ! No need to do anything: fields read from file in
360
          ! [[gs2_save:gs2_restore_many]]
361
       end if
362
    end if
363
  end subroutine set_initial_field_and_dist_fn_values
364
end module gs2_init
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc