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

gyrokinetics / gs2 / 2078172070

03 Oct 2025 09:22AM UTC coverage: 10.835% (+0.03%) from 10.806%
2078172070

push

gitlab-ci

David Dickinson
Merged in experimental/user_controlled_output_base_name (pull request #1184)

5049 of 46599 relevant lines covered (10.83%)

119786.99 hits per line

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

1.52
/src/init_g.f90
1
!> This module contains the subroutines which set the initial value of the
2
!> fields and the distribution function.
3
module init_g
4
  use abstract_config, only: abstract_config_type, CONFIG_MAX_NAME_LEN
5
  use constants, only: run_name_size
6
  implicit none
7

8
  private
9

10
  public :: ginit, ginitopt_restart_many, restart_file, get_restart_dir, set_restart_dir
11
  public :: init_init_g, finish_init_g, wnml_init_g, check_init_g, tstart
12
  public :: new_field_init, initial_condition_is_nonadiabatic_dfn, add_restart_dir_to_file
13
  public :: init_g_config_type, set_init_g_config, get_init_g_config
14
  
15
  ! knobs
16
  integer :: ginitopt_switch
17
  integer, parameter :: ginitopt_default = 1,  &
18
       ginitopt_xi = 3, ginitopt_xi2 = 4, ginitopt_rh = 5, ginitopt_zero = 6, &
19
       ginitopt_test3 = 7, ginitopt_convect = 8, &
20
       ginitopt_noise = 10, ginitopt_restart_many = 11, ginitopt_continue = 12, &
21
       ginitopt_nl = 13, ginitopt_kz0 = 14, ginitopt_restart_small = 15, &
22
       ginitopt_nl2 = 16, ginitopt_nl3 = 17, ginitopt_nl4 = 18, & 
23
       ginitopt_nl5 = 19, ginitopt_alf = 20, ginitopt_kpar = 21, &
24
       ginitopt_nl6 = 22, ginitopt_nl7 = 23, ginitopt_gs = 24, ginitopt_recon = 25, &
25
       ginitopt_nl3r = 26, ginitopt_smallflat = 27, ginitopt_harris = 28, &
26
       ginitopt_recon3 = 29, ginitopt_ot = 30, &
27
       ginitopt_zonal_only = 31, ginitopt_single_parallel_mode = 32, &
28
       ginitopt_all_modes_equal = 33, &
29
       ginitopt_default_odd = 34, ginitopt_restart_eig=35, ginitopt_no_zonal = 36, &
30
       ginitopt_stationary_mode = 37, ginitopt_cgyro = 38, ginitopt_random_sine = 39, &
31
       ginitopt_constant = 40
32

33
  real :: width0, dphiinit, phiinit, imfac, refac, zf_init, phifrac
34
  real :: init_spec_pow, k0
35
  real :: den0, upar0, tpar0, tperp0
36
  real :: den1, upar1, tpar1, tperp1
37
  real :: den2, upar2, tpar2, tperp2
38
  real :: tstart, scale, apar0
39
  logical :: chop_side, clean_init, left, even, new_field_init
40
  logical :: initial_condition_is_nonadiabatic_dfn
41
  character (len = run_name_size) :: restart_file !WARNING: This is also defined in gs2_save. This should be addressed
42
  character (len=150) :: restart_dir
43
  integer, dimension(2) :: ikk, itt
44
  integer, dimension(3) :: ikkk,ittt
45
  complex, dimension(3) :: phiamp, aparamp
46
  integer :: restart_eig_id
47
  integer :: max_mode
48

49
  ! These are used for the function ginit_single_parallel_mode, and specify the
50
  !  kparallel to initialize. In the case of  zero magnetic shear, of course, the box 
51
  ! is periodic in the parallel direction, and so only harmonics of the box size 
52
  ! (i.e. ikpar_init) are allowed  EGH</doc>
53
  integer :: ikpar_init
54
  real :: kpar_init
55

56
  !>  This is used  in linear runs with flow shear  in order to track the
57
  !! evolution of a single Lagrangian mode.
58
  integer :: ikx_init
59

60
  ! RN> for recon3
61
  real :: phiinit0 ! amplitude of equilibrium
62
  real :: phiinit_rand ! amplitude of random perturbation
63
  real :: a0,b0 ! amplitude of equilibrium Apara or By 
64
  ! if b0 /= 0, u0 is rescaled to give this By amplitude by overriding a0
65
  ! if a0 /= 0, u0 is rescaled to give this Apara amplitude
66
  logical :: null_phi, null_bpar, null_apar ! nullify fields
67
  ! if use_{Phi,Bpar,Apar} = F, override corresponding flags
68
  integer :: adj_spec ! adjust input parameter of this spec
69
  ! if = 0, just warn if given conditions are not satisfied
70
  character (len=20) :: eq_type = ''
71
  ! equilibrium type = 'sinusoidal', 'porcelli', 'doubleharris'
72
  real :: prof_width=-.05
73
  ! width of porcelli, doubleharris profile
74
  ! if negative, this gives the ratio to the box size
75
  integer :: eq_mode_n=0, eq_mode_u=1
76
  ! mode number in x for sinusoidal equilibrium
77
  logical :: input_check_recon=.false.
78
  complex :: ukxy_pt(3)
79
  ! <RN
80

81
  !> Whether to use the constant_random number
82
  !! generator, which always gives the same
83
  !! random numbers. Used for testing.
84
  logical :: constant_random_flag
85
  
86
  logical, parameter :: debug = .false.
87
  logical :: initialized = .false.
88

89
  interface do_chop_side
90
     module procedure do_chop_side_slice, do_chop_side_full
91
  end interface do_chop_side
92
  
93
  !> Used to represent the input configuration of init_g
94
  type, extends(abstract_config_type) :: init_g_config_type
95
     ! namelist : init_g_knobs
96
     ! indexed : false     
97

98
     !> Amplitude of equilibrium `Apara`: if `a0` is non-zero, \(u_0\) is
99
     !> rescaled to give this `Apara` amplitude
100
     real :: a0 = 0.0
101
     !> Used by [[init_g_knobs:ginit_option]] `"recon3"`: adjust input parameter
102
     !> of this species; if = 0, just warn if given conditions are not satisfied
103
     !>
104
     !> FIXME: What input parameter, what conditions?
105
     integer :: adj_spec = 0
106
     !> Used by [[init_g_knobs:ginit_option]] `"nl3r"`: set amplitude of `apar`
107
     !> if [[init_g_knobs:width0]] is negative
108
     real :: apar0 = 0.0
109
     !> Used in initialization for the Orszag-Tang 2D vortex problem
110
     !> ([[init_g_knobs:ginit_option]] `"ot"`). Controls size of `jpar` term.
111
     !> FIXME: Reference equations?
112
     complex, dimension(3) :: aparamp = cmplx(0.0,0.0)
113
     !> Amplitude of equilibrium `By`: if `b0` is non-zero, \(u_0\) is
114
     !> rescaled to give this `By` amplitude by overriding [[init_g_knobs:a0]]
115
     real :: b0 = 0.0
116
     !> Rarely needed. Forces asymmetry into initial condition. Warning: This
117
     !> does not behave as one may expect in flux tube simulations (see
118
     !> clean_init), this can be important as the default is to use chop_side
119
     logical :: chop_side = .true.
120
     !> Used with [[init_g_knobs:ginit_option]] `"noise"`. Ensures that in flux
121
     !> tube simulations the connected boundary points are initialised to the
122
     !> same value. Also allows for [[init_g_knobs:chop_side]] to behave
123
     !> correctly in flux tube simulations.
124
     logical :: clean_init = .true.
125
     !> Use the constant_random number generator, which always gives the same
126
     !> random numbers. Useful for testing.
127
     logical :: constant_random_flag = .false.
128
     !> Amplitude of zeroth density perturbation for [[init_g_knobs:ginit_option]]
129
     !> options:
130
     !>
131
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
132
     !> - `"kz0"` (see [[init_g:ginit_kz0]])
133
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
134
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
135
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
136
     !> - `"ot"` (see [[init_g:ginit_ot]])
137
     !> - `"recon"` (see [[init_g:ginit_recon]])
138
     real :: den0 = 1.0
139
     !> Amplitude of first density perturbation for [[init_g_knobs:ginit_option]]
140
     !> options:
141
     !>
142
     !> - `"gs"` (see [[init_g:ginit_gs]])
143
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
144
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
145
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
146
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
147
     !> - `"recon"` (see [[init_g:ginit_recon]])
148
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
149
     real :: den1 = 0.0
150
     !> Amplitude of second density perturbation for [[init_g_knobs:ginit_option]]
151
     !> options:
152
     !>
153
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
154
     !> - `"kz0"` (see [[init_g:ginit_kz0]])
155
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
156
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
157
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
158
     !> - `"recon"` (see [[init_g:ginit_recon]])
159
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
160
     real :: den2 = 0.0
161
     !> Amplitude of \(\phi\) for `"nl7"` (see [[init_g:ginit_nl7]])
162
     real :: dphiinit = 1.0
163
     !> Mode number in \(x\) for the sinusoidal equilbrium option of
164
     !> [[init_g_knobs:ginit_option]] `"recon3"` (see [[init_g:ginit_recon3]]),
165
     !> applies to density and temperatures
166
     integer :: eq_mode_n = 0
167
     !> Mode number in \(x\) for the sinusoidal equilbrium option of
168
     !> [[init_g_knobs:ginit_option]] `"recon3"` (see [[init_g:ginit_recon3]]),
169
     !> applies to parallel velocity
170
     integer :: eq_mode_u = 1
171
     !> Equilbrium choice for [[init_g_knobs:ginit_option]] `"recon3"` (see
172
     !> [[init_g:ginit_recon3]]). Choices are:
173
     !>
174
     !> - `"sinusoidal"`
175
     !> - `"porcelli"`
176
     !> - `"doubleharris"`
177
     character(len = 20) :: eq_type = 'sinusoidal'
178
     !> Sometimes initial conditions have definite parity; this picks the parity
179
     !> in those cases. Affects the following choices of
180
     !> [[init_g_knobs:ginit_option]]:
181
     !>
182
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
183
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
184
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
185
     !> - `"recon"` (see [[init_g:ginit_recon]])
186
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
187
     logical :: even = .true.
188
     !> Method for initialising `g`. There are many possible options, but the
189
     !> typical ones are:
190
     !>
191
     !>   - `"default"`: Gaussian in \(\theta\). See [[init_g_knobs:phiinit]],
192
     !>     [[init_g_knobs:width0]], [[init_g_knobs:chop_side]]
193
     !>   - `"default_odd"`: Guassian in \(\theta\) multiplied by \(\sin(\theta -
194
     !>     \theta_0)\). See [[init_g_knobs:phiinit]], [[init_g_knobs:width0]],
195
     !>     [[init_g_knobs:chop_side]]
196
     !>   - `"noise"`: Noise along field line. The recommended (but not default)
197
     !>     selection. See [[init_g_knobs:phiinit]], [[init_g_knobs:zf_init]]
198
     !>   - `"restart", "many"`: Restart, using `g` from restart files.
199
     !>   - `"single_parallel_mode"`: Initialise only with a single parallel mode
200
     !>     specified by either [[init_g_knobs:ikpar_init]] for periodic
201
     !>     boundary conditions or [[init_g_knobs:kpar_init]] for linked
202
     !>     boundary conditions. Intended for linear calculations.
203
     !>   - `"eig_restart"`: Uses the restart files written by the
204
     !>     eigensolver. Also see [[init_g_knobs:restart_eig_id]].
205
     !>   - `"random_sine"`: This option is notable as it attempts to make sure
206
     !>     that the initial condition satisfies the parallel boundary condition.
207
     !>
208
     !> All the options are detailed further in the [initialisation options
209
     !> documentation](../user_manual/initialisation.html)
210
     character(len = 20) :: ginit_option = "default"
211
     !> \(k_y\) indices of two modes to initialise for certain options
212
     integer, dimension(2) :: ikk = [1, 2]
213
     !> \(k_y\) indices of three modes to initialise for certain options
214
     integer, dimension(3) :: ikkk = [1, 2, 2]
215
     !> Parallel mode number to initialise for [[init_g_knobs:ginit_option]]
216
     !> `"single_parallel_mode"` with periodic boundary conditions
217
     integer :: ikpar_init = 0
218
     !> If greater than zero, initialise only the given \(k_x\) with
219
     !> [[init_g_knobs:ginit_option]] `"noise"`. This is useful for linear runs
220
     !> with flow shear, to track the evolution of a single Lagrangian mode.
221
     integer :: ikx_init = -1
222
     !> Amplitude of imaginary part of \(\phi\) for various
223
     !> [[init_g_knobs:ginit_option]] options
224
     real :: imfac = 0.0
225
     !> Initial spectrum power index. with
226
     !> [[init_g_knobs:ginit_option]] `"noise"`.
227
     real :: init_spec_pow = 0.0
228
     !> Do we want to include the explicit source terms and
229
     !> related timesteps when saving/restoring from the restart file.
230
     logical :: include_explicit_source_in_restart = .true.
231
     !> If true then the initial condition is used to set the non-adiabatic
232
     !> distribution function rather than the `g` evolved by GS2.
233
     logical :: initial_condition_is_nonadiabatic_dfn = .false.
234
     !> Print some debug information for [[init_g_knobs:ginit_option]] `"recon3"`
235
     logical :: input_check_recon = .false.
236
     !> \(k_x\) indices of two modes to initialise for certain options
237
     integer, dimension(2) :: itt = [1, 2]     
238
     !> \(k_x\) indices of three modes to initialise for certain options
239
     integer, dimension(3) :: ittt = [1, 2, 2]     
240
     !> Used in [[init_g_knobs:ginit_option]] "harris" and "convect".
241
     real :: k0 = 1.0
242
     !> Parallel mode number to initialise for [[init_g_knobs:ginit_option]]
243
     !> `"single_parallel_mode"` with linked boundary conditions
244
     real :: kpar_init = 0.0
245
     !> If [[init_g_knobs:chop_side]] is true, chop out left side in theta if
246
     !> true, right side if false. Applies to: FIXME: list of initial conditions
247
     logical :: left = .true.
248
     !> The maximum mode number to initialise for [[init_g_knobs:ginit_option]]
249
     !> `"random_sine"`. Actual maximum used will be lower of max_mode and `ntheta/8`
250
     integer :: max_mode = 128
251
     !> Change fields implicit initialisation somehow
252
     !>
253
     !> FIXME: Add documentation
254
     logical :: new_field_init = .true.
255
     !> "Nullify fields". Used by [[init_g_knobs:ginit_option]] `"recon3"`
256
     !>
257
     !> FIXME: Add documentation
258
     logical :: null_apar = .false.
259
     !> "Nullify fields". Used by [[init_g_knobs:ginit_option]] `"recon3"`
260
     !>
261
     !> FIXME: Add documentation
262
     logical :: null_bpar = .false.
263
     !> "Nullify fields". Used by [[init_g_knobs:ginit_option]] `"recon3"`
264
     !>
265
     !> FIXME: Add documentation
266
     logical :: null_phi = .false.
267
     !> Used in initialization for the Orszag-Tang 2D vortex problem.
268
     !>
269
     !> FIXME: expand
270
     complex, dimension(3) :: phiamp = cmplx(0.0,0.0)
271
     !> If doing multiple flux tube calculations, multiply
272
     !> [[init_g_knobs:phiinit]] by `(job * phifrac + 1)`. Allows for ensemble
273
     !> averaging of multiple flux tube calculations
274
     real :: phifrac = 0.1
275
     !> Average amplitude of initial perturbation of each Fourier mode. Used by
276
     !> most [[init_g_knobs:ginit_option]] options
277
     real :: phiinit = 1.0
278
     !> Amplitude of equilibrium. Used by [[init_g_knobs:ginit_option]] `"recon3"`
279
     real :: phiinit0 = 0.0
280
     !> Amplitude of random perturbation. Used by [[init_g_knobs:ginit_option]] `"recon3"`
281
     real :: phiinit_rand = 0.0
282
     !> Which processor is responsible for saving/reading potentials to/from restart
283
     !> files. If <0 then all procs write to restart files. If >= nproc then set to
284
     !> proc_to_save_fields = mod(proc_to_save_fields, nproc)
285
     integer :: proc_to_save_fields = 0
286
     !> Width of "porcelli", "doubleharris" profiles in
287
     !> [[init_g_knobs:ginit_option]] `"recon3"`. If negative, this gives the
288
     !> ratio to the box size
289
     real :: prof_width = -0.1
290
     !> Restart from many restart files. If false, use a single restart file:
291
     !> this requires GS2 to have been built with parallel netCDF.
292
     logical :: read_many = .false.
293
     !> Amplitude of real part of \(\phi\) for various
294
     !> [[init_g_knobs:ginit_option]] options
295
     real :: refac = 1.0
296
     !> Directory to read/write restart files to/from. Make sure this exists
297
     !> before running (see [[gs2_diagnostics_knobs:file_safety_check]])
298
     character(len = 150) :: restart_dir = "./"
299
     !> Used to select with eigensolver generated restart file to load. Sets
300
     !> `<id>` in `restart_file//eig_<id>//.<proc>` string used to set
301
     !> filename. Note that this is zero indexed.
302
     integer :: restart_eig_id = 0
303
     !> Basename of restart files
304
     !>
305
     !> @note gets a smart default
306
     character(len = run_name_size) :: restart_file = "restart_file_not_set.nc"
307
     !> Rescale amplitudes of fields for restart [[init_g_knobs:ginit_option]]
308
     !> options such as `"restart"`. Note that if `scale` is negative, the
309
     !> fields are scaled by `-scale / max(abs(phi))`!
310
     real :: scale = 1.0
311
     !> Amplitude of zeroth parallel temperature perturbation for
312
     !> [[init_g_knobs:ginit_option]] options:
313
     !>
314
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
315
     !> - `"kz0"` (see [[init_g:ginit_kz0]])
316
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
317
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
318
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
319
     !> - `"ot"` (see [[init_g:ginit_ot]])
320
     !> - `"recon"` (see [[init_g:ginit_recon]])
321
     real :: tpar0 = 0.0
322
     !> Amplitude of first parallel temperature perturbation for
323
     !> [[init_g_knobs:ginit_option]] options:
324
     !>
325
     !> - `"gs"` (see [[init_g:ginit_gs]])
326
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
327
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
328
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
329
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
330
     !> - `"recon"` (see [[init_g:ginit_recon]])
331
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
332
     real :: tpar1 = 0.0
333
     !> Amplitude of second parallel temperature perturbation for
334
     !> [[init_g_knobs:ginit_option]] options:
335
     !>
336
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
337
     !> - `"kz0"` (see [[init_g:ginit_kz0]])
338
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
339
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
340
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
341
     !> - `"recon"` (see [[init_g:ginit_recon]])
342
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
343
     real :: tpar2 = 0.0
344
     !> Amplitude of zeroth perpendicular temperature perturbation for
345
     !> [[init_g_knobs:ginit_option]] options:
346
     !>
347
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
348
     !> - `"kz0"` (see [[init_g:ginit_kz0]])
349
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
350
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
351
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
352
     !> - `"ot"` (see [[init_g:ginit_ot]])
353
     !> - `"recon"` (see [[init_g:ginit_recon]])
354
     real :: tperp0 = 0.0
355
     !> Amplitude of first perpendicular temperature perturbation for
356
     !> [[init_g_knobs:ginit_option]] options:
357
     !>
358
     !> - `"gs"` (see [[init_g:ginit_gs]])
359
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
360
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
361
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
362
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
363
     !> - `"recon"` (see [[init_g:ginit_recon]])
364
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
365
     real :: tperp1 = 0.0
366
     !> Amplitude of second perpendicular temperature perturbation for
367
     !> [[init_g_knobs:ginit_option]] options:
368
     !>
369
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
370
     !> - `"kz0"` (see [[init_g:ginit_kz0]])
371
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
372
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
373
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
374
     !> - `"recon"` (see [[init_g:ginit_recon]])
375
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
376
     real :: tperp2 = 0.0
377
     !> Force `t = tstart` at beginning of run
378
     real :: tstart = 0.0
379
     !> Perturbation amplitude of parallel velocity? Used by
380
     !> [[init_g_knobs:ginit_option]] `"recon3"`
381
     !>
382
     !> FIXME: Add documentation
383
     complex, dimension(3) :: ukxy_pt = cmplx(0.,0.)
384
     !> Amplitude of zeroth parallel velocity perturbation for
385
     !> [[init_g_knobs:ginit_option]] options:
386
     !>
387
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
388
     !> - `"kz0"` (see [[init_g:ginit_kz0]])
389
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
390
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
391
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
392
     !> - `"ot"` (see [[init_g:ginit_ot]])
393
     !> - `"recon"` (see [[init_g:ginit_recon]])
394
     real :: upar0 = 0.0
395
     !> Amplitude of first parallel velocity perturbation for
396
     !> [[init_g_knobs:ginit_option]] options:
397
     !>
398
     !> - `"gs"` (see [[init_g:ginit_gs]])
399
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
400
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
401
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
402
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
403
     !> - `"recon"` (see [[init_g:ginit_recon]])
404
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
405
     real :: upar1 = 0.0
406
     !> Amplitude of second parallel velocity perturbation for
407
     !> [[init_g_knobs:ginit_option]] options:
408
     !>
409
     !> - `"kpar"` (see [[init_g:ginit_kpar]])
410
     !> - `"kz0"` (see [[init_g:ginit_kz0]])
411
     !> - `"nl3"` (see [[init_g:ginit_nl3]])
412
     !> - `"nl3r"` (see [[init_g:ginit_nl3r]])
413
     !> - `"nl7"` (see [[init_g:ginit_nl7]])
414
     !> - `"recon"` (see [[init_g:ginit_recon]])
415
     !> - `"recon3"` (see [[init_g:ginit_recon3]])
416
     real :: upar2 = 0.0
417
     !> Width of initial perturbation Gaussian envelope in \(\theta\)
418
     real :: width0 = -3.5
419
     !> Amplitude of initial zonal flow perturbations relative to other modes
420
     real :: zf_init = 1.0
421
#include "init_g_overrides_and_bound_auto_gen.inc"
422
     procedure :: set_smart_defaults => set_smart_defaults_local
423
  end type init_g_config_type
424
  
425
  type(init_g_config_type) :: init_g_config
426
  
427
contains
428

429
  !> FIXME : Add documentation
430
  subroutine wnml_init_g(unit)
×
431
    implicit none
432
    integer, intent(in) :: unit
433
    call init_g_config%write(unit)
×
434
  end subroutine wnml_init_g
×
435

436
  !> FIXME : Add documentation  
437
  subroutine check_init_g(report_unit)
×
438
    use run_parameters, only : delt_option_switch, delt_option_auto
439
    use species, only : spec, has_electron_species
440
    use warning_helpers, only: not_exactly_equal
441
    implicit none
442
    integer, intent(in) :: report_unit
443
    select case (ginitopt_switch)
×
444
    case (ginitopt_default)
445
       write (report_unit, fmt="('Initial conditions:')")
×
446
       write (report_unit, fmt="('  Amplitude:        ',f10.4)") phiinit
×
447
       write (report_unit, fmt="('  Width in theta:   ',f10.4)") width0
×
448
       if (chop_side) then
×
449
          write (report_unit, fmt="('  Parity:   none')") 
×
450
       else
451
          write (report_unit, fmt="('  Parity:   even')") 
×
452
       end if
453

454
    case (ginitopt_kz0)
455
       write (report_unit, fmt="('Initial conditions:')")
×
456
       write (report_unit, fmt="('  Amplitude:        ',f10.4)") phiinit
×
457
       write (report_unit, fmt="('  Constant along field line',f10.4)") width0
×
458
       if (chop_side) then
×
459
          write (report_unit, *) 
×
460
          write (report_unit, fmt="('################# WARNING #######################')")
×
461
          write (report_unit, fmt="('  Parity:   none')") 
×
462
          write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
463
          write (report_unit, fmt="('Remedy: set chop_side = .false. in init_g_knobs.')") 
×
464
          write (report_unit, fmt="('################# WARNING #######################')")
×
465
          write (report_unit, *) 
×
466
       end if
467

468
    case (ginitopt_noise)
469
       write (report_unit, fmt="('Initial conditions:')")
×
470
       write (report_unit, fmt="('  Amplitude:        ',f10.4)") phiinit
×
471
       write (report_unit, fmt="('  Noise along field line.')") 
×
472
       if (not_exactly_equal(zf_init, 1.)) then
×
473
          write (report_unit, fmt="('  Zonal flows adjusted by factor of zf_init = ',f10.4)") zf_init
×
474
       end if
475

476
    case (ginitopt_kpar)
477
       write (report_unit, fmt="('Initial conditions:')")
×
478
       write (report_unit, fmt="('  Amplitude:             ',f10.4)") phiinit
×
479
       write (report_unit, fmt="('  Real part multiplier:  ',f10.4)") refac
×
480
       write (report_unit, fmt="('  Imag part multiplier:  ',f10.4)") imfac
×
481
       if (width0 > 0.) then
×
482
          write (report_unit, fmt="('  Gaussian envelope in theta with width:  ',f10.4)") width0
×
483
       end if
484
       if (chop_side) then
×
485
          write (report_unit, *) 
×
486
          write (report_unit, fmt="('################# WARNING #######################')")
×
487
          write (report_unit, fmt="('  Parity:   none')") 
×
488
          write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
489
          write (report_unit, fmt="('Remedy: set chop_side = .false. in init_g_knobs.')") 
×
490
          write (report_unit, fmt="('################# WARNING #######################')")
×
491
          write (report_unit, *) 
×
492
       end if
493
       if (den0 > epsilon(0.0) .or. den1 > epsilon(0.0) .or. den2 > epsilon(0.0)) then
×
494
          write (report_unit, *) 
×
495
          write (report_unit, fmt="('Initial density perturbation of the form:')")
×
496
          write (report_unit, fmt="('den0   + den1 * cos(theta) + den2 * cos(2.*theta)')")
×
497
          write (report_unit, *) 
×
498
          write (report_unit, fmt="('with den0 =',f7.4,' den1 = ',f7.4,' den2 = ',f7.4)") den0, den1, den2
×
499
       end if
500
       if (upar0 > epsilon(0.0) .or. upar1 > epsilon(0.0) .or. upar2 > epsilon(0.0)) then
×
501
          write (report_unit, *) 
×
502
          write (report_unit, fmt="('Initial parallel velocity perturbation of the form:')")
×
503
          write (report_unit, fmt="('upar0   + upar1 * sin(theta) + upar2 * sin(2.*theta)')")
×
504
          write (report_unit, fmt="('90 degrees out of phase with other perturbations.')")
×
505
          write (report_unit, *) 
×
506
          write (report_unit, fmt="('with upar0 =',f7.4,' upar1 = ',f7.4,' upar2 = ',f7.4)") upar0, upar1, upar2
×
507
       end if
508
       if (tpar0 > epsilon(0.0) .or. tpar1 > epsilon(0.0) .or. tpar2 > epsilon(0.0)) then
×
509
          write (report_unit, *) 
×
510
          write (report_unit, fmt="('Initial Tpar perturbation of the form:')")
×
511
          write (report_unit, fmt="('tpar0   + tpar1 * cos(theta) + tpar2 * cos(2.*theta)')")
×
512
          write (report_unit, *) 
×
513
          write (report_unit, fmt="('with tpar0 =',f7.4,' tpar1 = ',f7.4,' tpar2 = ',f7.4)") tpar0, tpar1, tpar2
×
514
       end if
515
       if (tperp0 > epsilon(0.0) .or. tperp1 > epsilon(0.0) .or. tperp2 > epsilon(0.0)) then
×
516
          write (report_unit, *) 
×
517
          write (report_unit, fmt="('Initial Tperp perturbation of the form:')")
×
518
          write (report_unit, fmt="('tperp0   + tperp1 * cos(theta) + tperp2 * cos(2.*theta)')")
×
519
          write (report_unit, *) 
×
520
          write (report_unit, fmt="('with tperp0 =',f7.4,' tperp1 = ',f7.4,' tperp2 = ',f7.4)") tperp0, tperp1, tperp2
×
521
       end if
522
       if (has_electron_species(spec)) then
×
523
          write (report_unit, *) 
×
524
          write (report_unit, fmt="('Field line average of g_electron subtracted off.')")
×
525
       end if
526

527
    case (ginitopt_gs)
528
       write (report_unit, fmt="('Initial conditions:')")
×
529
       write (report_unit, fmt="('  Randomly phased kpar=1 sines and cosines')") 
×
530
       write (report_unit, fmt="('  in density, upar, tpar, or tperp.')") 
×
531
       write (report_unit, fmt="('  Real part amplitude:  ',f10.4)") refac*phiinit
×
532
       write (report_unit, fmt="('  Imag part amplitude:  ',f10.4)") imfac*phiinit
×
533
       if (abs( den1)  > epsilon(0.0)) write (report_unit, fmt="('  Density amplitude:  ',f10.4)") den1
×
534
       if (abs( upar1) > epsilon(0.0)) write (report_unit, fmt="('  Upar amplitude:  ',f10.4)") upar1
×
535
       if (abs( tpar1) > epsilon(0.0)) write (report_unit, fmt="('  Tpar amplitude:  ',f10.4)") tpar1
×
536
       if (abs(tperp1) > epsilon(0.0)) write (report_unit, fmt="('  Tperp amplitude:  ',f10.4)") tperp1
×
537

538
    case (ginitopt_nl)
539
       write (report_unit, fmt="('Initial conditions:')")
×
540
       write (report_unit, fmt="('At most two k_perps excited, with amplitude = ',f10.4)") phiinit
×
541
       write (report_unit, fmt="(' First k_perp has ik = ',i3,' it = ',i3)") ikk(1), itt(1)
×
542
       write (report_unit, fmt="('Second k_perp has ik = ',i3,' it = ',i3)") ikk(2), itt(2)
×
543
       if (chop_side) then
×
544
          write (report_unit, fmt="('  Parity:   none')") 
×
545
       else
546
          write (report_unit, fmt="('  Parity:   even')") 
×
547
       end if
548
       write (report_unit, fmt="('Reality condition is enforced.')")
×
549
       
550
    case (ginitopt_nl2)
551
       write (report_unit, fmt="('Initial conditions:')")
×
552
       write (report_unit, fmt="('At most two k_perps excited, with amplitude = ',f10.4)") phiinit
×
553
       write (report_unit, fmt="(' First k_perp has ik = ',i3,' it = ',i3)") ikk(1), itt(1)
×
554
       write (report_unit, fmt="('Second k_perp has ik = ',i3,' it = ',i3)") ikk(2), itt(2)
×
555
       if (chop_side) then
×
556
          write (report_unit, fmt="('  Parity:   none')") 
×
557
       else
558
          write (report_unit, fmt="('  Parity:   even')") 
×
559
       end if
560
       write (report_unit, fmt="('Reality condition is enforced.')")
×
561
       write (report_unit, fmt="('g perturbation proportional to (1+v_parallel)*sin(theta)')")
×
562

563
    case (ginitopt_nl3)
564
       write (report_unit, fmt="('Initial conditions:')")
×
565
       write (report_unit, fmt="('At most two k_perps excited, with amplitude = ',f10.4)") phiinit
×
566
       write (report_unit, fmt="(' First k_perp has ik = ',i3,' it = ',i3)") ikk(1), itt(1)
×
567
       write (report_unit, fmt="('Second k_perp has ik = ',i3,' it = ',i3)") ikk(2), itt(2)
×
568
       write (report_unit, fmt="('  Real part multiplied by:  ',f10.4)") refac
×
569
       write (report_unit, fmt="('  Imag part multiplied by:  ',f10.4)") imfac
×
570
       if (width0 > 0.) then
×
571
          write (report_unit, fmt="('  Gaussian envelope in theta with width:  ',f10.4)") width0
×
572
       end if
573
       if (chop_side) then
×
574
          write (report_unit, fmt="('  Parity:   none')") 
×
575
       else
576
          write (report_unit, fmt="('  Parity:   even')") 
×
577
       end if
578
       write (report_unit, fmt="('Reality condition is enforced.')")
×
579
       if (den0 > epsilon(0.0) .or. den1 > epsilon(0.0) .or. den2 > epsilon(0.0)) then
×
580
          write (report_unit, *) 
×
581
          write (report_unit, fmt="('Initial density perturbation of the form:')")
×
582
          write (report_unit, fmt="('den0   + den1 * cos(theta) + den2 * cos(2.*theta)')")
×
583
          write (report_unit, *) 
×
584
          write (report_unit, fmt="('with den0 =',f7.4,' den1 = ',f7.4,' den2 = ',f7.4)") den0, den1, den2
×
585
       end if
586
       if (upar0 > epsilon(0.0) .or. upar1 > epsilon(0.0) .or. upar2 > epsilon(0.0)) then
×
587
          write (report_unit, *) 
×
588
          write (report_unit, fmt="('Initial parallel velocity perturbation of the form:')")
×
589
          write (report_unit, fmt="('upar0   + upar1 * cos(theta) + upar2 * cos(2.*theta)')")
×
590
          write (report_unit, fmt="('90 degrees out of phase with other perturbations.')")
×
591
          write (report_unit, *) 
×
592
          write (report_unit, fmt="('with upar0 =',f7.4,' upar1 = ',f7.4,' upar2 = ',f7.4)") upar0, upar1, upar2
×
593
       end if
594
       if (tpar0 > epsilon(0.0) .or. tpar1 > epsilon(0.0) .or. tpar2 > epsilon(0.0)) then
×
595
          write (report_unit, *) 
×
596
          write (report_unit, fmt="('Initial Tpar perturbation of the form:')")
×
597
          write (report_unit, fmt="('tpar0   + tpar1 * cos(theta) + tpar2 * cos(2.*theta)')")
×
598
          write (report_unit, *) 
×
599
          write (report_unit, fmt="('with tpar0 =',f7.4,' tpar1 = ',f7.4,' tpar2 = ',f7.4)") tpar0, tpar1, tpar2
×
600
       end if
601
       if (tperp0 > epsilon(0.0) .or. tperp1 > epsilon(0.0) .or. tperp2 > epsilon(0.0)) then
×
602
          write (report_unit, *) 
×
603
          write (report_unit, fmt="('Initial Tperp perturbation of the form:')")
×
604
          write (report_unit, fmt="('tperp0   + tperp1 * cos(theta) + tperp2 * cos(2.*theta)')")
×
605
          write (report_unit, *) 
×
606
          write (report_unit, fmt="('with tperp0 =',f7.4,' tperp1 = ',f7.4,' tperp2 = ',f7.4)") tperp0, tperp1, tperp2
×
607
       end if
608
       
609
    case (ginitopt_nl4)
610
       write (report_unit, fmt="('Initial conditions:')")
×
611
       write (report_unit, *) 
×
612
       write (report_unit, fmt="('################# WARNING #######################')")
×
613
       write (report_unit, fmt="('Under development for study of secondary instabilities.')")
×
614
       write (report_unit, fmt="('Scale factor:   ',f10.4)") scale
×
615
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
616
       write (report_unit, fmt="('################# WARNING #######################')")
×
617
       write (report_unit, *) 
×
618

619
    case (ginitopt_nl5)
620
       write (report_unit, fmt="('Initial conditions:')")
×
621
       write (report_unit, *) 
×
622
       write (report_unit, fmt="('################# WARNING #######################')")
×
623
       write (report_unit, fmt="('Under development for study of secondary instabilities.')")
×
624
       write (report_unit, fmt="('Scale factor:   ',f10.4)") scale
×
625
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
626
       write (report_unit, fmt="('################# WARNING #######################')")
×
627
       write (report_unit, *) 
×
628

629
    case (ginitopt_nl6)
630
       write (report_unit, fmt="('Initial conditions:')")
×
631
       write (report_unit, *) 
×
632
       write (report_unit, fmt="('################# WARNING #######################')")
×
633
       write (report_unit, fmt="('Change amplitude of a particular mode.')")
×
634
       write (report_unit, fmt="('Scale factor:   ',f10.4)") scale
×
635
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
636
       write (report_unit, fmt="('################# WARNING #######################')")
×
637
       write (report_unit, *) 
×
638

639
    case (ginitopt_xi)
640
       write (report_unit, fmt="('Initial conditions:')")
×
641
       write (report_unit, *) 
×
642
       write (report_unit, fmt="('################# WARNING #######################')")
×
643
       write (report_unit, fmt="('Perturbation proportional to pitch angle.')")
×
644
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
645
       write (report_unit, fmt="('################# WARNING #######################')")
×
646
       write (report_unit, *) 
×
647

648
    case (ginitopt_xi2)
649
       write (report_unit, fmt="('Initial conditions:')")
×
650
       write (report_unit, *) 
×
651
       write (report_unit, fmt="('################# WARNING #######################')")
×
652
       write (report_unit, fmt="('Perturbation proportional to function of pitch angle.')")
×
653
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
654
       write (report_unit, fmt="('################# WARNING #######################')")
×
655
       write (report_unit, *) 
×
656

657
    case (ginitopt_rh)
658
       write (report_unit, fmt="('Initial conditions:')")
×
659
       write (report_unit, *) 
×
660
       write (report_unit, fmt="('################# WARNING #######################')")
×
661
       write (report_unit, fmt="('Maxwellian perturbation in ik=1 mode.')")
×
662
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
663
       write (report_unit, fmt="('################# WARNING #######################')")
×
664
       write (report_unit, *) 
×
665

666
    case (ginitopt_alf)
667
       write (report_unit, fmt="('Initial conditions:')")
×
668
       write (report_unit, *) 
×
669
       write (report_unit, fmt="('################# WARNING #######################')")
×
670
       write (report_unit, fmt="('Ion dist fn proportional to v_parallel * sin(theta).')")
×
671
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
672
       write (report_unit, fmt="('################# WARNING #######################')")
×
673
       write (report_unit, *) 
×
674

675
    case (ginitopt_zero)
676
       write (report_unit, fmt="('Initial conditions:')")
×
677
       write (report_unit, *) 
×
678
       write (report_unit, fmt="('################# WARNING #######################')")
×
679
       write (report_unit, fmt="('Distribution function = 0.')")
×
680
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
681
       write (report_unit, fmt="('################# WARNING #######################')")
×
682
       write (report_unit, *) 
×
683

684
    case (ginitopt_test3)
685
       write (report_unit, fmt="('Initial conditions:')")
×
686
       write (report_unit, *) 
×
687
       write (report_unit, fmt="('################# WARNING #######################')")
×
688
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
689
       write (report_unit, fmt="('################# WARNING #######################')")
×
690
       write (report_unit, *) 
×
691

692
    case (ginitopt_convect)
693
       write (report_unit, fmt="('Initial conditions:')")
×
694
       write (report_unit, *) 
×
695
       write (report_unit, fmt="('################# WARNING #######################')")
×
696
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
697
       write (report_unit, fmt="('################# WARNING #######################')")
×
698
       write (report_unit, *) 
×
699

700
    case (ginitopt_restart_many)
701
       write (report_unit, fmt="('Initial conditions:')")
×
702
       write (report_unit, fmt="('Each PE restarts from its own NetCDF restart file.')") 
×
703

704
    case (ginitopt_restart_small)
705
       write (report_unit, fmt="('Initial conditions:')")
×
706
       write (report_unit, fmt="('Each PE restarts from its own NetCDF restart file.')") 
×
707
       write (report_unit, fmt="('with amplitudes scaled by factor of scale = ',f10.4)") scale
×
708
       write (report_unit, fmt="('Noise added with amplitude = ',f10.4)") phiinit
×
709

710
    case (ginitopt_continue)
711
       write (report_unit, fmt="('Initial conditions:')")
×
712
       write (report_unit, *) 
×
713
       write (report_unit, fmt="('################# WARNING #######################')")
×
714
       write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
715
       write (report_unit, fmt="('################# WARNING #######################')")
×
716
       write (report_unit, *) 
×
717

718
    case (ginitopt_cgyro)
719
       write (report_unit, fmt="('Initial conditions:')")
×
720
       write (report_unit, fmt="('  Amplitude:        ',f10.4)") phiinit
×
721
       write (report_unit, fmt="('Constant amplitude for ky!=0')")
×
722
       write (report_unit, fmt="('Zero amplitude for ky=0')")
×
723

724
    case (ginitopt_random_sine)
725
       write (report_unit, fmt="('Initial conditions:')")
×
726
       write (report_unit, fmt="('  Amplitude:        ',f10.4)") phiinit
×
727
       write (report_unit, fmt="('  Zonal amplitude:  ',f10.4)") zf_init
×
728
       write (report_unit, fmt="('  Max mode:         ',I0)") max_mode
×
729
       write (report_unit, fmt="(' Random sum of sine waves up to max_mode mode number')")
×
730

731
    case (ginitopt_constant)
732
       write (report_unit, fmt="('Initial conditions:')")
×
733
       write (report_unit, fmt="('  Amplitude:        ',f10.4)") phiinit
×
734
       write (report_unit, fmt="('  Zonal amplitude:  ',f10.4)") zf_init
×
735
       write (report_unit, fmt="(' Constant value')")
×
736
    end select
737

738
    if (ginitopt_switch == ginitopt_restart_many) then
×
739
       if (delt_option_switch == delt_option_auto) then
×
740
          write (report_unit, *) 
×
741
          write (report_unit, fmt="('This run is a continuation of a previous run.')") 
×
742
          write (report_unit, fmt="('The time step at the beginning of this run')") 
×
743
          write (report_unit, fmt="('will be taken from the end of the previous run.')") 
×
744
       else
745
          write (report_unit, *) 
×
746
          write (report_unit, fmt="('################# WARNING #######################')")
×
747
          write (report_unit, fmt="('This run is a continuation of a previous run.')") 
×
748
          write (report_unit, fmt="('The time step is being set by hand.')") 
×
749
          write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
750
          write (report_unit, fmt="('You probably want to set delt_option to be check_restart in the knobs namelist.')") 
×
751
          write (report_unit, fmt="('################# WARNING #######################')")
×
752
          write (report_unit, *) 
×
753
       end if
754
    end if
755

756
    if (delt_option_switch == delt_option_auto) then
×
757
       if (ginitopt_switch /= ginitopt_restart_many) then
×
758
          write (report_unit, *) 
×
759
          write (report_unit, fmt="('################# WARNING #######################')")
×
760
          write (report_unit, fmt="('This is not a normal continuation run.')") 
×
761
          write (report_unit, fmt="('You probably want to set delt_option to be default in the knobs namelist.')") 
×
762
          write (report_unit, fmt="('THIS IS PROBABLY AN ERROR.')") 
×
763
          write (report_unit, fmt="('################# WARNING #######################')")
×
764
          write (report_unit, *) 
×
765
       end if
766
    end if
767
  end subroutine check_init_g
×
768

769
  !> Join restart_dir to restart_file, accounting for potential existence
770
  !> of path in restart_file already.
771
  subroutine add_restart_dir_to_file(restart_dir, restart_file)
12✔
772
    use file_utils, only: dirname, basename
773
    character(len = *), intent(in out) :: restart_dir, restart_file
774
    ! prepend restart_dir to restart_file
775
    ! append trailing slash if not exists
776
    if (restart_dir(len_trim(restart_dir):) /= "/") restart_dir = trim(restart_dir)//"/"
12✔
777
    restart_file = dirname(restart_file) // trim(restart_dir) // basename(restart_file)
12✔
778
  end subroutine add_restart_dir_to_file
12✔
779

780
  !> FIXME : Add documentation
781
  subroutine init_init_g(init_g_config_in)
12✔
782
    use gs2_save, only: set_restart_file, proc_to_save_fields
783
    use mp, only: nproc
784
    implicit none
785
    type(init_g_config_type), intent(in), optional :: init_g_config_in    
786

787
    if (initialized) return
12✔
788
    initialized = .true.
12✔
789

790
    call read_parameters(init_g_config_in)
12✔
791
    call add_restart_dir_to_file(restart_dir, restart_file)
12✔
792
    call set_restart_file (restart_file)
12✔
793
    if (proc_to_save_fields >= 0) proc_to_save_fields = mod(proc_to_save_fields, nproc)
12✔
794
  end subroutine init_init_g
795

796
  !> FIXME : Add documentation  
797
  subroutine ginit (restarted, override_ginitopt_switch)
×
798
    use gs2_save, only: read_t0_from_restart_file
799
    use species, only: has_hybrid_electron_species, spec
800
    use mp, only: proc0
801
    use optionals, only: get_option_with_default
802
    implicit none
803
    logical, intent (out) :: restarted
804
    integer, intent(in), optional :: override_ginitopt_switch
805
    logical, save :: have_warned_about_hybrid = .false.
806
    integer :: ginitopt_actual
807

808
    ginitopt_actual = get_option_with_default(override_ginitopt_switch, ginitopt_switch)
×
809

810
    restarted = .false.
×
811
    select case (ginitopt_actual)
×
812
    case (ginitopt_default)
813
       call ginit_default(use_odd = .false.)
×
814
    case (ginitopt_default_odd)
815
       call ginit_default(use_odd = .true.)
×
816
    case (ginitopt_kz0)
817
       call ginit_kz0
×
818
    case (ginitopt_noise)
819
       call ginit_noise
×
820
    case (ginitopt_single_parallel_mode)
821
       call ginit_single_parallel_mode
×
822
    case (ginitopt_all_modes_equal)
823
       call ginit_all_modes_equal
×
824
    case (ginitopt_kpar)
825
       call ginit_kpar
×
826
    case (ginitopt_gs)
827
       call ginit_gs
×
828
    case (ginitopt_nl)
829
       call ginit_nl
×
830
    case (ginitopt_nl2)
831
       call ginit_nl2
×
832
    case (ginitopt_nl3)
833
       call ginit_nl3(include_apar = .false.)
×
834
    case (ginitopt_nl3r)
835
       call ginit_nl3(include_apar = .true.)
×
836
    case (ginitopt_harris)
837
       call ginit_harris
×
838
    case (ginitopt_nl4)
839
       ! in an old version, this line was commented out.  Thus, to recover some old
840
       ! results, you might need to comment out this line and...
841
       !       t0 = tstart
842
       call ginit_nl4
×
843
       call read_t0_from_restart_file (tstart)
×
844
       ! this line:
845
       !       tstart = t0
846
       restarted = .true.
×
847
       scale = 1.
×
848
    case (ginitopt_nl5)
849
       call ginit_nl5
×
850
       restarted = .true.
×
851
       scale = 1.
×
852
    case (ginitopt_recon)
853
       call ginit_recon
×
854
       restarted = .true.
×
855
       scale = 1.
×
856
    case (ginitopt_nl6)
857
       call ginit_nl6
×
858
       restarted = .true.
×
859
       scale = 1.
×
860
    case (ginitopt_nl7)
861
       call ginit_nl7
×
862
    case (ginitopt_xi)
863
       call ginit_xi
×
864
    case (ginitopt_xi2)
865
       call ginit_xi2
×
866
    case (ginitopt_rh)
867
       call ginit_rh
×
868
    case (ginitopt_alf)
869
       call ginit_alf
×
870
    case (ginitopt_zero)
871
       call ginit_zero
×
872
    case (ginitopt_test3)
873
       call ginit_test3
×
874
    case (ginitopt_convect)
875
       call ginit_convect
×
876
    case (ginitopt_restart_many)
877
       call ginit_restart_many 
×
878
       call read_t0_from_restart_file (tstart)
×
879
       restarted = .true.
×
880
       scale = 1.
×
881
    case (ginitopt_restart_eig)
882
       call ginit_restart_eig 
×
883
       call read_t0_from_restart_file (tstart)
×
884
       restarted = .true.
×
885
       scale = 1.
×
886
    case (ginitopt_restart_small)
887
       call ginit_restart_small
×
888
       call read_t0_from_restart_file (tstart)
×
889
       restarted = .true.
×
890
       scale = 1.
×
891
    case (ginitopt_zonal_only)
892
       call ginit_restart_zonal_only
×
893
       call read_t0_from_restart_file (tstart)
×
894
       restarted = .true.
×
895
       scale = 1.
×
896
    case (ginitopt_no_zonal)
897
       call ginit_restart_no_zonal
×
898
       call read_t0_from_restart_file (tstart)
×
899
       restarted = .true.
×
900
       scale = 1.
×
901
    case (ginitopt_smallflat)
902
       call ginit_restart_smallflat
×
903
       call read_t0_from_restart_file (tstart)
×
904
       restarted = .true.
×
905
       scale = 1.
×
906
    case (ginitopt_continue)
907
       restarted = .true.
×
908
       scale = 1.
×
909
    case (ginitopt_recon3)
910
       call ginit_recon3
×
911
    case (ginitopt_ot)
912
       call ginit_ot
×
913
    case (ginitopt_stationary_mode)
914
       call ginit_stationary_mode
×
915
    case (ginitopt_cgyro)
916
       call ginit_cgyro
×
917
    case (ginitopt_random_sine)
918
       call ginit_random_sine
×
919
    case (ginitopt_constant)
920
       call ginit_constant
×
921
    end select
922

923
    ! If the initial condition is the nonadiabatic dfn then
924
    ! ensure we've actually set `gnew` correctly.
925
    ! We avoid doing this if we're restarting as currently we assume
926
    ! that the restart files always contain our evolved gnew, rather
927
    ! than the nonadiabatic dfn.
928
    if (initial_condition_is_nonadiabatic_dfn .and. .not. restarted) then
×
929
       call set_gnew_from_nonadiabatic_dfn
×
930
    else
931
       ! If not restarting and have a hybrid electron species then
932
       ! issue a warning (once only) as recommend initialising the
933
       ! non-adiabatic dfn directly in this situation as this respects
934
       ! the hybrid electron h = 0 condition.
935
       if ((.not. restarted) .and. has_hybrid_electron_species(spec) &
936
            .and. (.not. have_warned_about_hybrid) .and. proc0) then
×
937
          have_warned_about_hybrid = .true.
×
938
          write(*,'("Warning : Running with a hybrid electron species but initial_condition_is_nonadiabatic_dfn is false.")')
×
939
       end if
940
    end if
941
    
942
  end subroutine ginit
×
943

944
  !> Take the existing gnew value and, assuming it is the nonadiabatic dfn,
945
  !> calculate the consistent potentials to set the true gnew value.
946
  subroutine set_gnew_from_nonadiabatic_dfn
×
947
    use dist_fn_arrays, only: gnew, g, g_adjust, to_g_gs2
948
    use dist_fn, only: calculate_potentials_from_nonadiabatic_dfn
949
    use species, only: spec, has_hybrid_electron_species
950
    use le_grids, only: is_passing_hybrid_electron
951
    use gs2_layouts, only: g_lo, ik_idx, il_idx, is_idx
952
    use fields_arrays, only: phi, apar, bpar, phinew, aparnew, bparnew
953
    use array_utils, only: copy
954
    implicit none
955
    integer :: iglo, ik, il, is
956

957
    ! Respect passing hybrid electrons h=0
958
    if (has_hybrid_electron_species(spec)) then
×
959
       do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
960
          is = is_idx(g_lo, iglo)
×
961
          ik = ik_idx(g_lo, iglo)
×
962
          il = il_idx(g_lo, iglo)
×
963
          if (is_passing_hybrid_electron(is, ik, il)) gnew(:,:,iglo) = 0.0
×
964
       end do
965
    end if
966

967
    ! Calculate the consistent potentials
968
    call calculate_potentials_from_nonadiabatic_dfn(gnew, phi, apar, bpar)
×
969

970
    ! Adjust the nonadiabatic dfn to give the actual gnew we evolve
971
    call g_adjust(gnew, phi, bpar, direction = to_g_gs2)
×
972

973
    ! Ensure both timesteps are set correctly
974
    call copy(gnew, g)
×
975
    call copy(phi, phinew)
×
976
    call copy(apar, aparnew)
×
977
    call copy(bpar, bparnew)
×
978
  end subroutine set_gnew_from_nonadiabatic_dfn
×
979

980
  !> Set the smart defaults for the init_g_config_type instance
981
  subroutine set_smart_defaults_local(self)
12✔
982
    use file_utils, only: run_name
983
    implicit none
984
    class(init_g_config_type), intent(in out) :: self
985
    if (self%is_initialised()) return
12✔
986
    if (.not. self%override_restart_file) self%restart_file = trim(run_name)//".nc"
12✔
987
  end subroutine set_smart_defaults_local
988

989
  !> FIXME : Add documentation
990
  subroutine read_parameters(init_g_config_in)
12✔
991
    use file_utils, only: error_unit
992
    use text_options, only: text_option, get_option_value
993
    use gs2_save, only: read_many, include_explicit_source_in_restart, proc_to_save_fields
994
    use mp, only: job
995
    implicit none
996
    type(init_g_config_type), intent(in), optional :: init_g_config_in
997

998
    type (text_option), dimension (*), parameter :: ginitopts = &
999
         [ text_option('default', ginitopt_default), &
1000
            text_option('default_odd', ginitopt_default_odd), &
1001
            text_option('noise', ginitopt_noise), &
1002
            text_option('xi', ginitopt_xi), &
1003
            text_option('xi2', ginitopt_xi2), &
1004
            text_option('zero', ginitopt_zero), &
1005
            text_option('test3', ginitopt_test3), &
1006
            text_option('convect', ginitopt_convect), &
1007
            text_option('rh', ginitopt_rh), &
1008
            text_option('restart', ginitopt_restart_many), &
1009
            text_option('many', ginitopt_restart_many), &
1010
            text_option('small', ginitopt_restart_small), &
1011
            text_option('file', ginitopt_restart_many), &
1012
            text_option('cont', ginitopt_continue), &
1013
            text_option('kz0', ginitopt_kz0), &
1014
            text_option('nl', ginitopt_nl), &
1015
            text_option('nl2', ginitopt_nl2), &
1016
            text_option('nl3', ginitopt_nl3), &
1017
            text_option('nl3r', ginitopt_nl3r), &
1018
            text_option('nl4', ginitopt_nl4), &
1019
            text_option('nl5', ginitopt_nl5), &
1020
            text_option('nl6', ginitopt_nl6), &
1021
            text_option('nl7', ginitopt_nl7), &
1022
            text_option('alf', ginitopt_alf), &
1023
            text_option('gs', ginitopt_gs), &
1024
            text_option('kpar', ginitopt_kpar), &
1025
            text_option('smallflat', ginitopt_smallflat), &
1026
            text_option('harris', ginitopt_harris), &
1027
            text_option('recon', ginitopt_recon), &
1028
            text_option('recon3', ginitopt_recon3), &
1029
            text_option('ot', ginitopt_ot), &
1030
            text_option('zonal_only', ginitopt_zonal_only), &
1031
            text_option('no_zonal', ginitopt_no_zonal), &
1032
            text_option('single_parallel_mode', ginitopt_single_parallel_mode), &
1033
            text_option('all_modes_equal', ginitopt_all_modes_equal), &
1034
            text_option('eig_restart', ginitopt_restart_eig), &
1035
            text_option('stationary_mode', ginitopt_stationary_mode), &
1036
            text_option('cgyro', ginitopt_cgyro), &
1037
            text_option('random_sine', ginitopt_random_sine), &
1038
            text_option('constant', ginitopt_constant) &
1039
            ]
1040
    character(20) :: ginit_option
1041

1042
    if (present(init_g_config_in)) init_g_config = init_g_config_in
12✔
1043
    call init_g_config%init(name = 'init_g_knobs', requires_index = .false.)
12✔
1044

1045
    ! Copy out internal values into module level parameters
1046
    associate(self => init_g_config)
1047
#include "init_g_copy_out_auto_gen.inc"
1048
    end associate
1049

1050
    ! MAB - allows for ensemble averaging of multiple flux tube calculations
1051
    ! job=0 if not doing multiple flux tube calculations, so phiinit unaffected
1052
    phiinit = phiinit * (job * phifrac + 1.0)
12✔
1053

1054
    call get_option_value &
1055
         (ginit_option, ginitopts, ginitopt_switch, &
1056
         error_unit(), "ginit_option in ginit_knobs",.true.)
12✔
1057
  end subroutine read_parameters
12✔
1058

1059
  !> Set initial condition to gaussian in \(\theta\)
1060
  !>
1061
  !> Controlled by:
1062
  !> - Amplitude: [[init_g_knobs:phiinit]]
1063
  !> - Width in \(\theta\): [[init_g_knobs:width0]]
1064
  !> - Parity: even about \(\theta_0\) unless [[init_g_knobs:chop_side]] is true
1065
  subroutine ginit_default(use_odd)
×
1066
    use species, only: spec
1067
    use theta_grid, only: ntgrid, theta
1068
    use kt_grids, only: naky, ntheta0, theta0, aky, enforce_reality
1069
    use le_grids, only: forbid
1070
    use dist_fn_arrays, only: g, gnew
1071
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
1072
    use array_utils, only: copy
1073
    use warning_helpers, only: is_zero
1074
    implicit none
1075
    logical, intent(in) :: use_odd
1076
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
1077
    integer :: iglo, ig, ik, it, il, is
1078

1079
    do ik = 1, naky
×
1080
       do it = 1, ntheta0
×
1081
          do ig = -ntgrid, ntgrid
×
1082
             phi(ig, it, ik) = exp(-((theta(ig)-theta0(it, ik))/width0)**2) * cmplx(1.0,1.0)
×
1083
          end do
1084
       end do
1085
    end do
1086
    if (use_odd) then
×
1087
       do ik = 1, naky
×
1088
          do it = 1, ntheta0
×
1089
             do ig = -ntgrid, ntgrid
×
1090
                phi(ig, it, ik) = phi(ig, it, ik) * sin((theta(ig)-theta0(it, ik))/width0)
×
1091
             end do
1092
          end do
1093
       end do
1094
    end if
1095

1096
    call do_chop_side(phi)
×
1097
    
1098
    if (enforce_reality) then
×
1099
       phi(:, 1, 1) = 0.0
×
1100
       if (naky > 1 .and. is_zero(aky(1))) phi(:, :, 1) = 0.0
×
1101
       call apply_reality(phi)
×
1102
    end if
1103

1104
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1105
       ik = ik_idx(g_lo, iglo)
×
1106
       it = it_idx(g_lo, iglo)
×
1107
       il = il_idx(g_lo, iglo)
×
1108
       is = is_idx(g_lo, iglo)
×
1109
       g(:, 1, iglo) = phi(:, it, ik) * spec(is)%z * phiinit
×
1110
       where (forbid(:, il)) g(:, 1, iglo) = 0.0
×
1111
       g(:, 2, iglo) = g(:, 1, iglo)
×
1112
    end do
1113
    call copy(g, gnew)
×
1114
  end subroutine ginit_default
×
1115

1116
  !> Initialise with only the kparallel = 0 mode. 
1117
  subroutine ginit_kz0
×
1118
    use species, only: spec
1119
    use theta_grid, only: ntgrid 
1120
    use kt_grids, only: naky, ntheta0, aky, enforce_reality
1121
    use le_grids, only: forbid
1122
    use dist_fn_arrays, only: g, gnew, vpa, vperp2
1123
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
1124
    use array_utils, only: copy
1125
    use warning_helpers, only: is_zero
1126
    implicit none
1127
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
1128
    integer :: iglo, ik, it, il, is
1129

1130
    phi = cmplx(refac,imfac)
×
1131
    call do_chop_side(phi)
×
1132
    
1133
    if (enforce_reality) then
×
1134
       phi(:,1,1) = 0.0
×
1135
       if (naky > 1 .and. is_zero(aky(1))) phi(:,:,1) = 0.0
×
1136
       call apply_reality(phi)
×
1137
    end if
1138

1139
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1140
       ik = ik_idx(g_lo,iglo)
×
1141
       it = it_idx(g_lo,iglo)
×
1142
       il = il_idx(g_lo,iglo)
×
1143
       is = is_idx(g_lo,iglo)
×
1144
       g(:,1,iglo) = -phi(:,it,ik)*spec(is)%z*phiinit*(den0 + sqrt(2.)*upar0*vpa(:,1,iglo) + tpar0*(vpa(:,1,iglo)**2-0.5) + tperp0*(vperp2(:,iglo)-1.))
×
1145
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1146
       g(:,2,iglo) = -phi(:,it,ik)*spec(is)%z*phiinit*(den0 + sqrt(2.)*upar0*vpa(:,2,iglo) + tpar0*(vpa(:,2,iglo)**2-0.5) + tperp0*(vperp2(:,iglo)-1.))
×
1147
    end do
1148
    call copy(g, gnew)
×
1149
  end subroutine ginit_kz0
×
1150

1151
  !> Initialise the distribution function with random noise. This is the
1152
  !> recommended initialisation option. Each different mode is given a random
1153
  !> amplitude between zero and one.
1154
  subroutine ginit_noise
×
1155
    use species, only: spec, tracer_species
1156
    use theta_grid, only: ntgrid 
1157
    use kt_grids, only: l_links, r_links, naky, ntheta0, aky, enforce_reality, akx, kperp2
1158
    use le_grids, only: forbid
1159
    use dist_fn_arrays, only: g, gnew
1160
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx, proc_id
1161
    use dist_fn, only: pass_right, init_pass_ends, has_linked_boundary
1162
    use redistribute, only: fill, delete_redist
1163
    use ran, only: ranf
1164
    use constant_random, only: init_constant_random
1165
    use constant_random, only: finish_constant_random
1166
    use constant_random, only: constant_ranf=>ranf
1167
    use array_utils, only: copy, zero_array
1168
    use constants, only: twopi
1169
    use warning_helpers, only: is_zero
1170
    implicit none
1171
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi, phit
×
1172
    real :: a, b, spec_pow
1173
    integer :: iglo, ig, ik, it, il, is, nn
1174
    logical :: linked_bc
1175

1176
    linked_bc = has_linked_boundary()
×
1177

1178
    !CMR: need to document tracer phit parameter   ;-)
1179
    call zero_array(phit)
×
1180
    do it=2,ntheta0/2+1
×
1181
       nn = it-1
×
1182
       ! extra factor of 4 to reduce the high k wiggles for now
1183
       phit (:, it, 1) = (-1)**nn*exp(-8.*(real(nn)/ntheta0)**2)
×
1184
    end do
1185
    
1186
    ! keep old (it, ik) loop order to get old results exactly: 
1187

1188
    !Fill phi with random (complex) numbers between -0.5 and 0.5
1189
    if (constant_random_flag) call init_constant_random
×
1190
    do it = 1, ntheta0
×
1191
       do ik = 1, naky
×
1192
          do ig = -ntgrid, ntgrid
×
1193
             if (constant_random_flag) then
×
1194
                a = constant_ranf()-0.5
×
1195
                b = constant_ranf()-0.5
×
1196
             else
1197
                a = ranf()-0.5
×
1198
                b = ranf()-0.5
×
1199
             end if
1200
             if (init_spec_pow > 0.) then
×
1201
                spec_pow = 1./sqrt(1.+kperp2(ig,it,ik)**(0.5*init_spec_pow))
×
1202
                phi(ig,it,ik) = spec_pow*exp(cmplx(0.,twopi*a))
×
1203
             else
1204
                phi(ig,it,ik) = cmplx(a,b)
×
1205
             end if
1206
          end do
1207
          !CMR,28/1/13:
1208
          ! clean_init debrutalises influence of chop_side on phi with linked bc
1209
          if (chop_side) then
×
1210
             if (clean_init .and. linked_bc) then
×
1211
                if (left) then
×
1212
                   !Does this tube have more links to the right than the left?
1213
                   !If so then it's on the left so set to zero
1214
                   if (l_links(it, ik) < r_links(it, ik)) then
×
1215
                      phi(:,it,ik) = 0.0 
×
1216
                      !This tube is in the middle so only set the left half to 0
1217
                   else if (l_links(it, ik) == r_links(it, ik)) then
×
1218
                      phi(:-1,it,ik) = 0.0
×
1219
                   endif
1220
                else
1221
                   !Does this tube have more links to the left than the right?
1222
                   !If so then it's on the right so set to zero
1223
                   if (r_links(it, ik) < l_links(it, ik)) then
×
1224
                      phi(:,it,ik) = 0.0
×
1225
                      !This tube is in the middle so only set the right half to 0
1226
                   else if (l_links(it, ik) == r_links(it, ik)) then
×
1227
                      phi(1:,it,ik) = 0.0
×
1228
                   endif
1229
                end if
1230
             else
1231
                call do_chop_side(phi(:, it, ik))
×
1232
             end if
1233
          end if
1234
       end do
1235
    end do
1236
    if (constant_random_flag) call finish_constant_random
×
1237

1238
    !Wipe out all but one kx if requested
1239
    if (ikx_init  > 0) call single_initial_kx(phi)
×
1240
    
1241
    !Sort out the zonal/self-periodic modes
1242
    if (naky >= 1 .and. is_zero(aky(1))) then
×
1243
       !Apply scaling factor
1244
       phi(:,:,1) = phi(:,:,1)*zf_init
×
1245
       
1246
       !Set ky=kx=0.0 mode to zero in amplitude
1247
       if (is_zero(akx(1))) phi(:,1,1) = 0.0
×
1248
       
1249
       !CMR, 25/1/13: clean_init forces periodic zonal flows
1250
       if (clean_init .and. linked_bc) then
×
1251
          phi(ntgrid,:,1)=phi(-ntgrid,:,1)
×
1252
          phit(ntgrid,:,1)=phit(-ntgrid,:,1)
×
1253
       end if
1254
    end if
1255

1256
    if (enforce_reality) then
×
1257
       call apply_reality(phi)
×
1258
       call apply_reality(phit)
×
1259
    end if
1260

1261
    !Now set g using data in phi
1262
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1263
       ik = ik_idx(g_lo,iglo)
×
1264
       it = it_idx(g_lo,iglo)
×
1265
       il = il_idx(g_lo,iglo)
×
1266
       is = is_idx(g_lo,iglo)
×
1267

1268
       !Handle tracer_species 
1269
       if (spec(is)%type == tracer_species) then          
×
1270
          g(:,1,iglo) =-phit(:,it,ik)*spec(is)%z*phiinit
×
1271
       else
1272
          g(:,1,iglo) = -phi(:,it,ik)*spec(is)%z*phiinit
×
1273
       end if
1274

1275
       !Make sure there's no g in the forbidden regions
1276
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1277
     
1278
       !Set incoming and outgoing boundary conditions
1279
       if ( clean_init .and. linked_bc .and. ik > 1) then
×
1280
          !CMR: clean_init sets g=0 for incoming particles, 
1281
          !                         and outgoing particles
1282
          !                      as initial condition sets g(:,1,:) = g(:,2,:) )
1283
          !If no links to the left then we're at the left boundary
1284
          if ( l_links(it, ik) == 0 ) g(-ntgrid,1,iglo)=0.0
×
1285
          !If no links to the right then we're at the right boundary
1286
          if ( r_links(it, ik) == 0 ) g(ntgrid,1,iglo)=0.0
×
1287
       endif
1288
    end do
1289

1290
    
1291
    !If clean_init is set and there are any links/connections then make sure repeated points are consistent
1292
    if ( clean_init .and. linked_bc .and. sum(r_links+l_links) > 0 ) then
×
1293
       !   
1294
       !CMR, 23/1/13:  
1295
       !  clean_init: ensure continuity in || direction with linked bcs
1296
       !  set up redistribute type pass_right 
1297
       !  this passes g(ntgrid,1,iglo) to g(-ntgrid,1,iglo_r) on right neighbour 
1298

1299
       !Initialise communications object !NOTE This should be moved to dist_fn in future
1300
       call init_pass_ends(pass_right,'r',1,'c')
×
1301

1302
       !Pass right boundaries (ntgrid) of g to linked left boundaries (-ntgrid) of g
1303
       call fill(pass_right,g,g)
×
1304

1305
       !Deallocate comm object as not used anywhere else !NOTE This will need removing if/when initialisation moved to dist_fn
1306
       call delete_redist(pass_right)
×
1307

1308
       !Make leftwards and rightwards particles the same
1309
       g(:,2,:)=g(:,1,:)
×
1310

1311
       !Set gnew to be the "fixed" data
1312
       call copy(g, gnew)
×
1313
    else 
1314
! finally initialise isign=2
1315
       g(:,2,:) = g(:,1,:)
×
1316
       call copy(g, gnew)
×
1317
    endif
1318

1319
  end subroutine ginit_noise
×
1320

1321
  !> Initialise only with a single parallel mode \(k_\Vert\) specified by either
1322
  !> [[init_g_knobs:ikpar_init]] for periodic boundary conditions or
1323
  !> [[init_g_knobs:kpar_init]] for linked boundary conditions. Only makes sense
1324
  !> for linear calculations.
1325
  subroutine ginit_single_parallel_mode
×
1326
    use species, only: spec, tracer_species
1327
    use theta_grid, only: ntgrid, is_effectively_zero_shear, theta, shat
1328
    use kt_grids, only: naky, ntheta0, aky, enforce_reality
1329
    use le_grids, only: forbid
1330
    use mp, only: mp_abort
1331
    use dist_fn_arrays, only: g, gnew
1332
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
1333
    use array_utils, only: copy, zero_array
1334
    use warning_helpers, only: is_zero
1335
    implicit none
1336
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi, phit
×
1337
    real :: a, b
1338
    integer :: iglo, ig, ik, it, il, is, nn
1339

1340
    call zero_array(phit)
×
1341
    do it=2,ntheta0/2+1
×
1342
       nn = it-1
×
1343
       ! extra factor of 4 to reduce the high k wiggles for now
1344
       phit (:, it, 1) = (-1)**nn*exp(-8.*(real(nn)/ntheta0)**2)
×
1345
    end do
1346

1347
    if (is_effectively_zero_shear() .or. is_zero(shat)) then
×
1348
      if (ikpar_init+1 > ntgrid) then
×
1349
        call mp_abort("Error: this value of k_parallel is too large. Increase ntheta or decrease ikpar_init.")
×
1350
      end if
1351
      kpar_init = ikpar_init
×
1352
    end if
1353

1354
    do it = 1, ntheta0
×
1355
       do ik = 1, naky
×
1356
          do ig = -ntgrid, ntgrid
×
1357
             !Set the field to cos(kpar_init*theta), where we remember
1358
             !that the gridpoints are not necessarily evenly spaced in
1359
             !the parallel direction, so we use theta(ig).  reality
1360
             !for ky=0 means we must use -kpar for kx < 0
1361
             a = cos(kpar_init * theta(ig))
×
1362
             b = sin(kpar_init * theta(ig))
×
1363
             phi(ig,it,ik) = cmplx(a,b)
×
1364
          end do
1365
       end do
1366
    end do
1367

1368
    call do_chop_side(phi)
×
1369
    if (naky > 1 .and. is_zero(aky(1))) phi(:,:,1) = phi(:,:,1) * zf_init
×
1370
    if (ikx_init  > 0) call single_initial_kx(phi)
×
1371

1372
    if (enforce_reality) then
×
1373
       call apply_reality(phi)
×
1374
       call apply_reality(phit)
×
1375
    end if
1376
       
1377
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1378
       ik = ik_idx(g_lo,iglo)
×
1379
       it = it_idx(g_lo,iglo)
×
1380
       il = il_idx(g_lo,iglo)
×
1381
       is = is_idx(g_lo,iglo)
×
1382
       if (spec(is)%type == tracer_species) then          
×
1383
          g(:,1,iglo) =-phit(:,it,ik)*spec(is)%z*phiinit
×
1384
       else
1385
          g(:,1,iglo) = -phi(:,it,ik)*spec(is)%z*phiinit
×
1386
       end if
1387
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1388
       g(:,2,iglo) = g(:,1,iglo)
×
1389
    end do
1390
    call copy(g, gnew)
×
1391
  end subroutine ginit_single_parallel_mode
×
1392

1393
  !> Initialize with every parallel and perpendicular mode having equal amplitude. 
1394
  !! Only makes sense in a linear calculation. k_parallel is specified with kpar_init 
1395
  !! or with ikpar_init when periodic boundary conditions are used. EGH 
1396
  subroutine ginit_all_modes_equal
×
1397
    use species, only: spec, tracer_species
1398
    use theta_grid, only: ntgrid, theta, ntheta 
1399
    use kt_grids, only: naky, ntheta0, enforce_reality
1400
    use le_grids, only: forbid
1401
    use dist_fn_arrays, only: g, gnew
1402
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
1403
    use array_utils, only: copy, zero_array
1404
    use warning_helpers, only: is_zero
1405
    implicit none
1406
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi, phit
×
1407
    real :: a, b
1408
    integer :: iglo, ig, ik, it, il, is, nn, ikpar
1409

1410
    call zero_array(phit)
×
1411
    do it=2,ntheta0/2+1
×
1412
       nn = it-1
×
1413
       ! extra factor of 4 to reduce the high k wiggles for now
1414
       phit (:, it, 1) = (-1)**nn*exp(-8.*(real(nn)/ntheta0)**2)
×
1415
    end do
1416

1417
    do it = 1, ntheta0
×
1418
       do ik = 1, naky
×
1419
          do ig = -ntgrid, ntgrid
×
1420
             ! Set the field to cos(kpar*theta) for all kpar, where we remember that the gridpoints are not necessarily evenly spaced in the parallel direction, so we use theta(ig)</doc>
1421
             a = 0.0
×
1422
             b = 0.0
×
1423
             do ikpar = 0, ntheta - 1
×
1424
                a = a + cos(ikpar * theta(ig))
×
1425
                ! we want to include the positive and negative wave numbers in
1426
                ! equal measure, which of course means a real sine wave.
1427
                b = 0.0 !b + cos(ikpar * theta(ig))
×
1428
             end do
1429
             phi(ig,it,ik) = cmplx(a,b)
×
1430
          end do
1431
       end do
1432
    end do
1433

1434
    call do_chop_side(phi)
×
1435
    if (ikx_init  > 0) call single_initial_kx(phi)
×
1436

1437
    if (enforce_reality) then
×
1438
       call apply_reality(phi)
×
1439
       call apply_reality(phit)
×
1440
    end if
1441
       
1442
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1443
       ik = ik_idx(g_lo,iglo)
×
1444
       it = it_idx(g_lo,iglo)
×
1445
       il = il_idx(g_lo,iglo)
×
1446
       is = is_idx(g_lo,iglo)
×
1447
       if (spec(is)%type == tracer_species) then          
×
1448
          g(:,1,iglo) =-phit(:,it,ik)*spec(is)%z*phiinit
×
1449
       else
1450
          g(:,1,iglo) = -phi(:,it,ik)*spec(is)%z*phiinit
×
1451
       end if
1452
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1453
       g(:,2,iglo) = g(:,1,iglo)
×
1454
    end do
1455
    call copy(g, gnew)
×
1456
  end subroutine ginit_all_modes_equal
×
1457

1458
  !> "nl": Two \(k_\perp\) modes set to constant amplitude. Controlled by:
1459
  !>
1460
  !>  - Overall amplitude: [[init_g_knobs:phiinit]]
1461
  !>  - `ky` indices of modes: [[init_g_knobs:ikk]]
1462
  !>  - `kx` indices of modes: [[init_g_knobs:itt]]
1463
  !>  - Parity: even about \(\theta_0\) unless
1464
  !>    [[init_g_knobs:chop_side]] is true, in which case none
1465
  subroutine ginit_nl
×
1466
    use species, only: spec
1467
    use theta_grid, only: ntgrid 
1468
    use kt_grids, only: naky, ntheta0 
1469
    use le_grids, only: forbid, il_is_wfb
1470
    use dist_fn_arrays, only: g, gnew
1471
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
1472
    use array_utils, only: copy, zero_array
1473
    implicit none
1474
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
1475
    integer :: iglo, ig, ik, it, il, is, j
1476
    call zero_array(phi)
×
1477
    do j = 1, 2
×
1478
       ik = ikk(j)
×
1479
       it = itt(j)
×
1480
       do ig = -ntgrid, ntgrid
×
1481
          phi(ig,it,ik) = cmplx(1.0, 0.0)!*sin(theta(ig))
×
1482
       end do
1483
       call do_chop_side(phi(:, it, ik))
×
1484
    end do
1485

1486
    call apply_reality(phi)
×
1487

1488
    ! charge dependence keeps initial Phi from being too small
1489
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1490
       ik = ik_idx(g_lo,iglo)
×
1491
       it = it_idx(g_lo,iglo)
×
1492
       il = il_idx(g_lo,iglo)
×
1493
       is = is_idx(g_lo,iglo)       
×
1494
       g(:,1,iglo) = -phi(:,it,ik)*phiinit*spec(is)%z
×
1495
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1496
       g(:,2,iglo) = g(:,1,iglo)
×
1497
       if (il_is_wfb(il)) g(:,:,iglo) = 0.0
×
1498
    end do
1499
    call copy(g, gnew)
×
1500
  end subroutine ginit_nl
×
1501

1502
  !> "nl2": Two \(k_\perp\) modes proportional to \(1 + v_\Vert
1503
  !>     \sin(\theta)\). Controlled by:
1504
  !>
1505
  !>  - Overall amplitude: [[init_g_knobs:phiinit]]
1506
  !>  - `ky` indices of modes: [[init_g_knobs:ikk]]
1507
  !>  - `kx` indices of modes: [[init_g_knobs:itt]]
1508
  !>  - Parity: even about \(\theta_0\) unless
1509
  !>    [[init_g_knobs:chop_side]] is true, in which case none
1510
  subroutine ginit_nl2
×
1511
    use species, only: spec
1512
    use theta_grid, only: ntgrid, theta
1513
    use kt_grids, only: naky, ntheta0 
1514
    use le_grids, only: forbid, il_is_wfb
1515
    use dist_fn_arrays, only: g, gnew, vpa
1516
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
1517
    use array_utils, only: copy, zero_array
1518
    implicit none
1519
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
1520
    integer :: iglo, ig, ik, it, il, is, j
1521
    call zero_array(phi)
×
1522
    do j = 1, 2
×
1523
       ik = ikk(j)
×
1524
       it = itt(j)
×
1525
       do ig = -ntgrid, ntgrid
×
1526
          phi(ig,it,ik) = cmplx(1.0, 0.0)!*sin(theta(ig))
×
1527
       end do
1528
       call do_chop_side(phi(:, it, ik))
×
1529
    end do
1530

1531
    call apply_reality(phi)
×
1532
    
1533
    ! charge dependence keeps initial Phi from being too small
1534
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1535
       ik = ik_idx(g_lo,iglo)
×
1536
       it = it_idx(g_lo,iglo)
×
1537
       il = il_idx(g_lo,iglo)
×
1538
       is = is_idx(g_lo,iglo)       
×
1539
       g(:,1,iglo) = -phi(:,it,ik)*phiinit*(1.+vpa(:,1,iglo)*sin(theta))*spec(is)%z
×
1540
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1541
       g(:,2,iglo) = -phi(:,it,ik)*phiinit*(1.+vpa(:,2,iglo)*sin(theta))*spec(is)%z
×
1542
       if (il_is_wfb(il)) g(:,:,iglo) = 0.0
×
1543
    end do
1544
    call copy(g, gnew)
×
1545
  end subroutine ginit_nl2
×
1546

1547
  !> "nl3": Two \(k_\perp\) modes with a Gaussian envelope, and perturbation in
1548
  !> fields of form \(x_0 + x_1 \cos(\theta) + x_2 \cos(2 \theta)\), except for
1549
  !> parallel velocity which uses is 90 degrees out of phase and uses
1550
  !> \(\sin\). Density, parallel velocity, and perpendicular and parallel
1551
  !> temperatures can all be controlled independently. Controlled by:
1552
  !>
1553
  !>   - Overall amplitude: [[init_g_knobs:phiinit]]
1554
  !>   - Amplitude of real and imaginary parts of \(\phi\):
1555
  !>     [[init_g_knobs:refac]], [[init_g_knobs:imfac]]
1556
  !>   - Gaussian envelope width in \(\theta\): [[init_g_knobs:width0]]
1557
  !>   - `ky` indices of modes: [[init_g_knobs:ikk]]
1558
  !>   - `kx` indices of modes: [[init_g_knobs:itt]]
1559
  !>   - Parity: even about \(\theta_0\) unless
1560
  !>     [[init_g_knobs:chop_side]] is true, in which case none
1561
  !>   - Density perturbation: [[init_g_knobs:den0]],
1562
  !>     [[init_g_knobs:den1]], [[init_g_knobs:den2]]
1563
  !>   - Parallel velocity perturbation: [[init_g_knobs:upar0]],
1564
  !>     [[init_g_knobs:upar1]], [[init_g_knobs:upar2]]
1565
  !>   - Parallel temperature perturbation: [[init_g_knobs:tpar0]],
1566
  !>     [[init_g_knobs:tpar1]], [[init_g_knobs:tpar2]]
1567
  !>   - Perpendicular temperature perturbation: [[init_g_knobs:tperp0]],
1568
  !>     [[init_g_knobs:tperp1]], [[init_g_knobs:tperp2]]
1569
  subroutine ginit_nl3(include_apar)
×
1570
    use theta_grid, only: ntgrid, theta
1571
    use kt_grids, only: naky, ntheta0, theta0, enforce_reality
1572
    use dist_fn_arrays, only: g, gnew
1573
    use array_utils, only: copy, zero_array
1574
    use fields_arrays, only: apar, aparnew
1575
    implicit none
1576
    logical, intent(in) :: include_apar
1577
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
1578
    integer :: ig, ik, it, j
1579
    call zero_array(phi)
×
1580
    do j = 1, 2
×
1581
       ik = ikk(j)
×
1582
       it = itt(j)
×
1583
       if (width0 > 0.) then
×
1584
          do ig = -ntgrid, ntgrid
×
1585
             phi(ig,it,ik) = exp(-((theta(ig)-theta0(it,ik))/width0)**2)*cmplx(refac, imfac)
×
1586
          end do
1587
       else
1588
          do ig = -ntgrid, ntgrid
×
1589
             phi(ig,it,ik) = cmplx(refac, imfac)
×
1590
          end do
1591
          if (include_apar) apar(:, it, ik) = apar0 * phi(:, it, ik)
×
1592
       end if
1593
       call do_chop_side(phi(:, it, ik))
×
1594
    end do
1595

1596
    if (enforce_reality .and. include_apar) call apply_reality(apar)
×
1597
    if (include_apar) call copy(apar, aparnew)
×
1598

1599
    call set_g_from_moment_facs(g, phiinit, phi, dfac_species_weight = .true., &
1600
         ufac_species_weight = .true., use_even = even, do_reality = enforce_reality)
×
1601
    call copy(g, gnew)
×
1602
  end subroutine ginit_nl3
×
1603

1604
  !> FIXME : Add documentation  
1605
  subroutine ginit_harris
×
1606
    use species, only: spec, has_electron_species
1607
    use kt_grids, only: naky, ntheta0, enforce_reality, nx
1608
    use le_grids, only: forbid
1609
    use dist_fn_arrays, only: g, gnew, vpa, aj0
1610
    use gs2_layouts, only: g_lo, ik_idx, it_idx, is_idx, il_idx
1611
    use constants, only: zi, pi
1612
    use array_utils, only: copy, zero_array
1613
    implicit none
1614
    complex, dimension (1,ntheta0,naky) :: phi
×
1615
    integer :: iglo, ik, it, il, is, j, j1
1616
    real, dimension(nx) :: lx_pr, a_pr
×
1617
    complex,dimension(nx) :: ff_pr
×
1618
    real:: L, dx_pr
1619
    !
1620
    ! Specifying function on x grid, with nx points.  Transforming to kx grid, with
1621
    ! nkx < nx points.  Result is function that will be used for initial condition.
1622
    ! But Fourier transform is the same if you just use nkx points in the first
1623
    ! place, right?
1624
    !
1625

1626
    ! Can specify x0 along with y0; no need to use this construction, although it is okay.
1627
    L=2.*pi*k0
×
1628

1629
    ! nx is available from kt_grids:
1630
    dx_pr=L/real(nx)
×
1631

1632
    do j = 1, nx
×
1633
       lx_pr(j)=dx_pr*real(j-1)
×
1634
    end do
1635

1636
    do j = 1,nx
×
1637
       a_pr(j)=1./cosh((lx_pr(j)-L/4.)/width0)- &
×
1638
         1./cosh((lx_pr(j)-3.*L/4.)/width0)
×
1639
    end do
1640

1641
    a_pr=a_pr/real(nx)
×
1642

1643
    do j = 1,nx
×
1644
       ff_pr(j) = 0.
×
1645
       do j1 = 1,nx
×
1646
          ff_pr(j)=ff_pr(j)+a_pr(j1)*exp(-zi*2.*pi*real(j-1)*real(j1-1)/real(nx))
×
1647
       end do
1648
    end do
1649

1650
    call zero_array(phi)
×
1651

1652
    ! Dealiasing here:
1653
    do j = 1, ntheta0/2-1
×
1654
       phi(1,j,1) = ff_pr(j)
×
1655
    end do
1656

1657
    ! Note: if the j=1 coefficient is non-zero, it might be a problem, because this
1658
    ! coefficient is never used.
1659
    do j = ntheta0/2, ntheta0
×
1660
       phi(1,j,1) = ff_pr(nx-ntheta0+j)
×
1661
    end do
1662

1663
    if (enforce_reality) call apply_reality(phi)
×
1664
    
1665
    call zero_array(g)
×
1666
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1667
       ik = ik_idx(g_lo,iglo)
×
1668
       it = it_idx(g_lo,iglo) 
×
1669
       il = il_idx(g_lo,iglo) 
×
1670
       is = is_idx(g_lo,iglo)       
×
1671
    
1672
       ! ions, kx/=0:
1673
       if ((is==1) .and.(.not.(it==1))) then
×
1674
       
1675
          g(:,1,iglo) =  2.* vpa(:,1,iglo)*spec(is)%u0 * phi(1,it,ik)/aj0(:,iglo)
×
1676
          g(:,2,iglo) =  2.* vpa(:,2,iglo)*spec(is)%u0 * phi(1,it,ik)/aj0(:,iglo)
×
1677

1678
          where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1679
          where (forbid(:,il)) g(:,2,iglo) = 0.0
×
1680
          
1681
       end if
1682
    end do
1683
    call copy(g, gnew)
×
1684
  end subroutine ginit_harris
×
1685

1686
  !> FIXME : Add documentation  
1687
  subroutine ginit_recon
×
1688
    use theta_grid, only: ntgrid
1689
    use kt_grids, only: naky, ntheta0, enforce_reality
1690
    use gs2_save, only: gs2_restore
1691
    use dist_fn_arrays, only: g, gnew
1692
    use fields_arrays, only: phi, apar, bpar, phinew, aparnew, bparnew
1693
    use gs2_layouts, only: g_lo, ik_idx
1694
    use run_parameters, only: has_phi, has_apar, has_bpar
1695
    use array_utils, only: copy, zero_array
1696
    implicit none
1697
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phiz
×
1698
    integer :: iglo, ig, ik, it, j
1699
    
1700
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
1701

1702
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1703
       ik = ik_idx(g_lo,iglo)
×
1704
       if (ik == 1) cycle
×
1705
       g (:, :, iglo) = 0.
×
1706
    end do
1707

1708
    phinew(:,:,2:naky) = 0.
×
1709
    aparnew(:,:,2:naky) = 0.
×
1710
    bparnew(:,:,2:naky) = 0.
×
1711
    phi(:,:,2:naky) = 0.
×
1712
    apar(:,:,2:naky) = 0.
×
1713
    bpar(:,:,2:naky) = 0.
×
1714

1715
    call zero_array(phiz)
×
1716
    do j = 1, 2
×
1717
       ik = ikk(j)
×
1718
       it = itt(j)
×
1719
       do ig = -ntgrid, ntgrid
×
1720
          phiz(ig,it,ik) = cmplx(refac, imfac)
×
1721
       end do
1722
    end do
1723

1724
    call set_g_from_moment_facs(g, phiinit, phiz, dfac_species_weight = .true., &
1725
         ufac_species_weight = .false., use_even = even, do_reality = enforce_reality)
×
1726
    call copy(g, gnew)
×
1727
  end subroutine ginit_recon
×
1728

1729
  !> FIXME : Add documentation
1730
  !!
1731
  !! @note nl4 has been monkeyed with over time.  Do not expect to recover old results
1732
  !! that use this startup routine.
1733
  subroutine ginit_nl4
×
1734
    use species, only: spec
1735
    use gs2_save, only: gs2_restore
1736
    use theta_grid, only: ntgrid
1737
    use kt_grids, only: naky, ntheta0
1738
    use dist_fn_arrays, only: g, gnew
1739
    use le_grids, only: forbid
1740
    use fields_arrays, only: phi, apar, bpar
1741
    use fields_arrays, only: phinew, aparnew, bparnew
1742
    use gs2_layouts, only: g_lo, ik_idx, it_idx, is_idx, il_idx
1743
    use run_parameters, only: has_phi, has_apar, has_bpar
1744
    use ran, only: ranf
1745
    use array_utils, only: copy, zero_array
1746
    implicit none
1747
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phiz
×
1748
    integer :: iglo, ig, ik, it, is, il
1749
    
1750
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
1751

1752
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1753
       it = it_idx(g_lo,iglo)
×
1754
       ik = ik_idx(g_lo,iglo)
×
1755
       if (it == 1 .and. ik == 2) cycle
×
1756
       g (:,:,iglo) = 0.
×
1757
    end do
1758

1759
    do ik = 1, naky
×
1760
       do it=1,ntheta0
×
1761
          if (it == 1 .and. ik == 2) cycle
×
1762
          phinew(:,it,ik) = 0.
×
1763
          aparnew(:,it,ik) = 0.
×
1764
          bparnew(:,it,ik) = 0.
×
1765
          phi(:,it,ik) = 0.
×
1766
          apar(:,it,ik) = 0.
×
1767
          bpar(:,it,ik) = 0.          
×
1768
       end do
1769
    end do
1770
    
1771
    do ik = 1, naky
×
1772
       do it = 1, ntheta0
×
1773
          do ig = -ntgrid, ntgrid
×
1774
             phiz(ig,it,ik) = cmplx(ranf()-0.5,ranf()-0.5)
×
1775
          end do
1776
       end do
1777
    end do
1778

1779
    call do_chop_side(phiz)
×
1780
    call apply_reality(phiz)
×
1781

1782
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1783
       ik = ik_idx(g_lo,iglo)
×
1784
       it = it_idx(g_lo,iglo)
×
1785
       il = il_idx(g_lo,iglo)
×
1786
       is = is_idx(g_lo,iglo)
×
1787
       g(:,1,iglo) = g(:,1,iglo)-phiz(:,it,ik)*spec(is)%z*phiinit
×
1788
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1789
       g(:, 2, iglo) = g(:, 1, iglo)
×
1790
    end do
1791
    call copy(g, gnew)
×
1792
  end subroutine ginit_nl4
×
1793

1794
  !> FIXME : Add documentation. This is near identical to ginit_nl4 aside from initial zeroing
1795
  subroutine ginit_nl5
×
1796
    use species, only: spec
1797
    use gs2_save, only: gs2_restore
1798
    use theta_grid, only: ntgrid
1799
    use kt_grids, only: naky, ntheta0
1800
    use dist_fn_arrays, only: g, gnew
1801
    use le_grids, only: forbid
1802
    use fields_arrays, only: phi, apar, bpar
1803
    use fields_arrays, only: phinew, aparnew, bparnew
1804
    use gs2_layouts, only: g_lo, ik_idx, it_idx, is_idx, il_idx
1805
    use run_parameters, only: has_phi, has_apar, has_bpar
1806
    use ran, only: ranf
1807
    use array_utils, only: copy, zero_array
1808
    implicit none
1809
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phiz
×
1810
    integer :: iglo, ig, ik, it, is, il
1811
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
1812

1813
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1814
       ik = ik_idx(g_lo, iglo)
×
1815
       if (ik == 1) cycle
×
1816
       g (:, :, iglo) = 0.
×
1817
    end do
1818

1819
    phinew(:,:,2:naky) = 0.
×
1820
    aparnew(:,:,2:naky) = 0.
×
1821
    bparnew(:,:,2:naky) = 0.
×
1822
    phi(:,:,2:naky) = 0.
×
1823
    apar(:,:,2:naky) = 0.
×
1824
    bpar(:,:,2:naky) = 0.
×
1825

1826
    do ik = 1, naky
×
1827
       do it = 1, ntheta0
×
1828
          do ig = -ntgrid, ntgrid
×
1829
             phiz(ig,it,ik) = cmplx(ranf()-0.5,ranf()-0.5)
×
1830
          end do
1831
       end do
1832
    end do
1833

1834
    call do_chop_side(phiz)
×
1835
    call apply_reality(phiz)
×
1836

1837
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1838
       ik = ik_idx(g_lo,iglo)
×
1839
       it = it_idx(g_lo,iglo)
×
1840
       il = il_idx(g_lo,iglo)
×
1841
       is = is_idx(g_lo,iglo)
×
1842
       g(:,1,iglo) = g(:,1,iglo)-phiz(:,it,ik)*phiinit*spec(is)%z
×
1843
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
1844
       g(:, 2, iglo) = g(:, 1, iglo)
×
1845
    end do
1846
    call copy(g, gnew)
×
1847
  end subroutine ginit_nl5
×
1848

1849
  !> FIXME : Add documentation  
1850
  subroutine ginit_nl6
×
1851
    use gs2_save, only: gs2_restore
1852
    use kt_grids, only: ntheta0
1853
    use dist_fn_arrays, only: g, gnew
1854
    use fields_arrays, only: phi, apar, bpar
1855
    use fields_arrays, only: phinew, aparnew, bparnew
1856
    use gs2_layouts, only: g_lo, ik_idx, it_idx, is_idx, il_idx
1857
    use run_parameters, only: has_phi, has_apar, has_bpar
1858
    use array_utils, only: copy, zero_array
1859
    implicit none
1860
    integer :: iglo, ik, it
1861
    
1862
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
1863
    call zero_array(gnew)
×
1864

1865
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1866
       ik = ik_idx(g_lo,iglo)
×
1867
       it = it_idx(g_lo,iglo)
×
1868
       if (ik == 1 .and. it == 2) cycle
×
1869
       if (ik == 1 .and. it == ntheta0) cycle
×
1870
       g(:,:,iglo) = 0.
×
1871
    end do
1872

1873
    phinew(:,2,1) = 0.   
×
1874
    aparnew(:,2,1) = 0.
×
1875
    bparnew(:,2,1) = 0.
×
1876

1877
    phi(:,2,1) = 0.
×
1878
    apar(:,2,1) = 0.
×
1879
    bpar(:,2,1) = 0.
×
1880

1881
    phinew(:,ntheta0,1) = 0.
×
1882
    aparnew(:,ntheta0,1) = 0.
×
1883
    bparnew(:,ntheta0,1) = 0.
×
1884

1885
    phi(:,ntheta0,1) = 0.
×
1886
    apar(:,ntheta0,1) = 0.
×
1887
    bpar(:,ntheta0,1) = 0.
×
1888

1889
    call copy(g, gnew)
×
1890
  end subroutine ginit_nl6
×
1891

1892
  !> FIXME : Add documentation  
1893
  subroutine ginit_nl7
×
1894
    use theta_grid, only: ntgrid
1895
    use kt_grids, only: naky, ntheta0, enforce_reality
1896
    use dist_fn_arrays, only: g, gnew
1897
    use array_utils, only: copy
1898
    implicit none
1899
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
1900
    integer :: ig, ik, it, j
1901
    do it = 1, ntheta0
×
1902
       do ik = 1, naky
×
1903
          phi(:,it,ik) = cmplx(refac,imfac) * dphiinit
×
1904
       end do
1905
    end do
1906

1907
    do j = 1, 2
×
1908
       ik = ikk(j)
×
1909
       it = itt(j)
×
1910
       do ig = -ntgrid, ntgrid
×
1911
          phi(ig,it,ik) = cmplx(refac, imfac)
×
1912
       end do
1913
    end do
1914

1915
    call set_g_from_moment_facs(g, phiinit, phi, dfac_species_weight = .true., &
1916
         ufac_species_weight = .false., use_even = even, do_reality = enforce_reality)
×
1917
    call copy(g, gnew)
×
1918
  end subroutine ginit_nl7
×
1919

1920
  !> Orszag-Tang 2D vortex problem
1921
  subroutine ginit_ot
×
1922
    use species, only: spec
1923
    use theta_grid, only: ntgrid
1924
    use kt_grids, only: naky, nakx => ntheta0, enforce_reality, kperp2
1925
    use dist_fn_arrays, only: g, gnew, vpa
1926
    use gs2_layouts, only: g_lo, ik_idx, it_idx, is_idx
1927
    use fields_arrays, only: phinew, aparnew, bparnew
1928
    use dist_fn, only: get_init_field
1929
    use array_utils, only: copy, zero_array
1930
    implicit none
1931
    integer :: iglo, ik, it, is, i
1932
    complex :: fac
1933
    complex, dimension (-ntgrid:ntgrid,nakx,naky) :: phi, jpar ! local !
×
1934
    real, dimension (-ntgrid:ntgrid) :: dfac, ufac
×
1935

1936
    !! phi, jpar are local !!
1937
    call zero_array(phi) ; call zero_array(jpar)
×
1938
    !$    phi(:,1,2) = phiinit * cmplx(2.0, 0.0)  ! 2 cos(y)
1939
    !$    phi(:,2,1) = phiinit * cmplx(1.0, 0.0)  ! 2 cos(x)
1940
    !$    jpar(:,1,2) = apar0 * cmplx(2.0, 0.0) ! 2 cos(y)
1941
    !$    jpar(:,3,1) = apar0 * cmplx(2.0, 0.0) ! 4 cos(2x)
1942
    do i=1, 3
×
1943
       it = ittt(i)
×
1944
       ik = ikkk(i)
×
1945
       phi(:,it,ik) = phiamp(i)
×
1946
       jpar(:,it,ik) = aparamp(i) * kperp2(:,it,ik)
×
1947
    end do
1948

1949
    if (enforce_reality) then
×
1950
       call apply_reality(phi)
×
1951
       call apply_reality(jpar)
×
1952
    end if
1953

1954
    dfac     = den0
×
1955
    ufac     = upar0
×
1956

1957
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1958
       it = it_idx(g_lo,iglo)
×
1959
       ik = ik_idx(g_lo,iglo)
×
1960
       is = is_idx(g_lo,iglo)
×
1961

1962
       g(:,1,iglo) = &
×
1963
            ( dfac*spec(is)%dens0                * phi(:,it,ik) &
×
1964
            + 2.*ufac* vpa(:,1,iglo)*spec(is)%u0 * jpar(:,it,ik) )
×
1965

1966
       g(:,2,iglo) = &
×
1967
            ( dfac*spec(is)%dens0                * phi(:,it,ik) &
×
1968
            + 2.*ufac* vpa(:,2,iglo)*spec(is)%u0 * jpar(:,it,ik) )
×
1969

1970
    end do
1971

1972
    call copy(g, gnew)
×
1973

1974
    ! normalize
1975
    call get_init_field (phinew, aparnew, bparnew)
×
1976
    do i=1, 3
×
1977
       it = ittt(i)
×
1978
       ik = ikkk(i)
×
1979
       if (abs(phiamp(i)) > epsilon(0.0)) then
×
1980
          ! Should this include abs?
1981
          fac = phiamp(i) / phinew(0,it,ik)
×
1982
          phi(:,it,ik) = phi(:,it,ik) * fac
×
1983
       end if
1984
       if (abs(aparamp(i)) > epsilon(0.0)) then
×
1985
          fac = aparamp(i) / aparnew(0,it,ik)
×
1986
          jpar(:,it,ik) = jpar(:,it,ik) * fac
×
1987
       end if
1988
    end do
1989

1990
    if (enforce_reality) then
×
1991
       call apply_reality(phi)
×
1992
       call apply_reality(jpar)
×
1993
    end if
1994

1995
    ! redefine g
1996
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
1997
       it = it_idx(g_lo,iglo)
×
1998
       ik = ik_idx(g_lo,iglo)
×
1999
       is = is_idx(g_lo,iglo)
×
2000

2001
       g(:,1,iglo) = &
×
2002
            ( dfac*spec(is)%dens0                * phi(:,it,ik) &
×
2003
            + 2.*ufac* vpa(:,1,iglo)*spec(is)%u0 * jpar(:,it,ik) )
×
2004

2005
       g(:,2,iglo) = &
×
2006
            ( dfac*spec(is)%dens0                * phi(:,it,ik) &
×
2007
            + 2.*ufac* vpa(:,2,iglo)*spec(is)%u0 * jpar(:,it,ik) )
×
2008

2009
    end do
2010
    call copy(g, gnew)
×
2011
  end subroutine ginit_ot
×
2012

2013
  !> FIXME : Add documentation
2014
  subroutine ginit_kpar
×
2015
    use species, only: spec, has_electron_species
2016
    use theta_grid, only: ntgrid, theta
2017
    use kt_grids, only: naky, ntheta0, theta0
2018
    use dist_fn_arrays, only: g, gnew
2019
    use array_utils, only: copy
2020
    implicit none
2021
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
2022
    integer :: ig
2023
    
2024
    if (width0 > 0.) then
×
2025
       do ig = -ntgrid, ntgrid
×
2026
          phi(ig,:,:) = exp(-((theta(ig)-theta0(:,:))/width0)**2)*cmplx(refac, imfac)
×
2027
       end do
2028
    else
2029
       do ig = -ntgrid, ntgrid
×
2030
          phi(ig,:,:) = cmplx(refac, imfac)
×
2031
       end do
2032
    end if
2033

2034
    call do_chop_side(phi)
×
2035

2036
    call set_g_from_moment_facs(g, phiinit, phi, dfac_species_weight = .false., &
2037
         ufac_species_weight = .false., use_even= .true., do_reality = .false.)
×
2038

2039
    if (has_electron_species(spec)) then
×
2040
       call flae (g, gnew)
×
2041
       g = g - gnew
×
2042
    end if
2043
    call copy(g, gnew)
×
2044
  end subroutine ginit_kpar
×
2045

2046
  !> FIXME : Add documentation  
2047
  subroutine ginit_gs
×
2048
    use species, only: spec, has_electron_species
2049
    use theta_grid, only: ntgrid, theta
2050
    use kt_grids, only: naky, ntheta0
2051
    use le_grids, only: forbid
2052
    use dist_fn_arrays, only: g, gnew, vpa, vperp2
2053
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
2054
    use constants, only: pi, zi
2055
    use ran, only: ranf
2056
    use array_utils, only: copy
2057
    implicit none
2058
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi, odd
×
2059
    integer :: iglo, ik, it, il, is
2060
    real :: phase
2061
    do ik=1,naky
×
2062
       do it=1,ntheta0
×
2063
          phase = 2.*pi*ranf()
×
2064
          phi(:,it,ik) = cos(theta+phase)*cmplx(refac,imfac)
×
2065
          odd(:,it,ik) = sin(theta+phase)*cmplx(refac,imfac) * zi
×
2066
       end do
2067
    end do
2068
  
2069
    !Should this be triggered for kt_grids::reality=.true. only?
2070
    call apply_reality(phi)
×
2071
    call apply_reality(odd)
×
2072

2073
    ! charge dependence keeps initial Phi from being too small
2074
    ! Note not quite suitable for set_g_from_moment_facs as dfac --> den1 etc.
2075
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2076
       ik = ik_idx(g_lo,iglo)
×
2077
       it = it_idx(g_lo,iglo)
×
2078
       il = il_idx(g_lo,iglo)
×
2079
       is = is_idx(g_lo,iglo)       
×
2080

2081
       g(:,1,iglo) = phiinit* &!spec(is)%z* &
×
2082
            ( den1                         * phi(:,it,ik) &
×
2083
            + 2.*upar1* vpa(:,1,iglo)      * odd(:,it,ik) &
×
2084
            + tpar1*(vpa(:,1,iglo)**2-0.5) * phi(:,it,ik) &
×
2085
            + tperp1*(vperp2(:,iglo)-1.)   * phi(:,it,ik))
×
2086
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
2087
       
2088
       g(:,2,iglo) = phiinit* &!spec(is)%z* &
×
2089
            ( den1                         * phi(:,it,ik) &
×
2090
            + 2.*upar1* vpa(:,2,iglo)      * odd(:,it,ik) &
×
2091
            + tpar1*(vpa(:,2,iglo)**2-0.5) * phi(:,it,ik) &
×
2092
            + tperp1*(vperp2(:,iglo)-1.)   * phi(:,it,ik))
×
2093
       where (forbid(:,il)) g(:,2,iglo) = 0.0
×
2094

2095
    end do
2096

2097
    if (has_electron_species(spec)) then
×
2098
       call flae (g, gnew)
×
2099
       g = g - gnew
×
2100
    end if
2101

2102
    call copy(g, gnew)
×
2103
  end subroutine ginit_gs
×
2104

2105
  !> FIXME : Add documentation  
2106
  subroutine ginit_xi
×
2107
    use theta_grid, only: ntgrid, theta, bmag
2108
    use le_grids, only: forbid, al
2109
    use kt_grids, only: theta0
2110
    use dist_fn_arrays, only: g, gnew
2111
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx
2112
    use array_utils, only: copy
2113
    implicit none
2114
    integer :: iglo, ik, it, il
2115
    real, dimension(-ntgrid:ntgrid) :: xi
×
2116

2117
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2118
       ik = ik_idx(g_lo,iglo)
×
2119
       it = it_idx(g_lo,iglo)
×
2120
       il = il_idx(g_lo,iglo)
×
2121
       xi = sqrt(max(1.0-bmag*al(il),0.0))
×
2122
       g(:,1,iglo) = xi*exp(-((theta-theta0(it,ik))/width0)**2)
×
2123
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
2124
       g(:,2,iglo) = -g(:,1,iglo)
×
2125
    end do
2126
    call copy(g, gnew)
×
2127
  end subroutine ginit_xi
×
2128

2129
  !> FIXME : Add documentation  
2130
  subroutine ginit_xi2
×
2131
    use theta_grid, only: ntgrid, theta, bmag
2132
    use le_grids, only: forbid, al
2133
    use kt_grids, only: theta0
2134
    use dist_fn_arrays, only: g, gnew
2135
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx
2136
    use array_utils, only: copy
2137
    implicit none
2138
    integer :: iglo, ik, it, il
2139
    real, dimension(-ntgrid:ntgrid) :: xi
×
2140

2141
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2142
       ik = ik_idx(g_lo,iglo)
×
2143
       it = it_idx(g_lo,iglo)
×
2144
       il = il_idx(g_lo,iglo)
×
2145
       xi = sqrt(max(1.0-bmag*al(il),0.0))
×
2146
       g(:,1,iglo) = (1.0 - 3.0*xi*xi)*exp(-((theta-theta0(it,ik))/width0)**2)
×
2147
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
2148
       g(:,2,iglo) = g(:,1,iglo)
×
2149
    end do
2150
    call copy(g, gnew)
×
2151
  end subroutine ginit_xi2
×
2152

2153
  !> FIXME : Add documentation  
2154
  subroutine ginit_rh
×
2155
    use le_grids, only: forbid, energy
2156
    use dist_fn_arrays, only: g, gnew
2157
    use gs2_layouts, only: g_lo, il_idx, ie_idx, is_idx
2158
    use array_utils, only: copy    
2159
    implicit none
2160
    integer :: iglo, il, ie, is
2161

2162
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2163
       il = il_idx(g_lo,iglo)
×
2164
       ie = ie_idx(g_lo,iglo)
×
2165
       is = is_idx(g_lo,iglo)
×
2166
       g(:,1,iglo) = exp(-energy(ie,is))
×
2167
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
2168
       g(:,2,iglo) = g(:,1,iglo)
×
2169
    end do
2170
    call copy(g, gnew)
×
2171
  end subroutine ginit_rh
×
2172

2173
  !> FIXME : Add documentation
2174
  subroutine ginit_alf
×
2175
    use theta_grid, only: theta
2176
    use le_grids, only: forbid
2177
    use dist_fn_arrays, only: g, gnew, vpa
2178
    use gs2_layouts, only: g_lo, il_idx, is_idx
2179
    use species, only: spec, is_electron_species
2180
    use array_utils, only: copy
2181
    implicit none
2182
    integer :: iglo, il, is
2183

2184
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2185
       is = is_idx(g_lo,iglo)
×
2186
       if (is_electron_species(spec(is))) cycle
×
2187
       il = il_idx(g_lo,iglo)
×
2188
       g(:,1,iglo) = sin(theta)*vpa(:,1,iglo)*spec(is)%z
×
2189
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
2190
       g(:,2,iglo) = sin(theta)*vpa(:,2,iglo)*spec(is)%z
×
2191
       where (forbid(:,il)) g(:,2,iglo) = 0.0
×
2192
    end do
2193
    g = phiinit * g 
×
2194
    call copy(g, gnew)
×
2195
  end subroutine ginit_alf
×
2196

2197
  !> FIXME : Add documentation
2198
  subroutine ginit_zero
×
2199
    use dist_fn_arrays, only: g, gnew
2200
    use array_utils, only: zero_array
2201
    implicit none
2202
    call zero_array(g)
×
2203
    call zero_array(gnew)
×
2204
  end subroutine ginit_zero
×
2205

2206
  !> FIXME : Add documentation  
2207
  subroutine ginit_test3
×
2208
    use dist_fn_arrays, only: g, gnew, vpa
2209
    use theta_grid, only: ntgrid, delthet, bmag
2210
    use kt_grids, only: akx
2211
    use theta_grid_params, only: eps, epsl, pk
2212
    use gs2_layouts, only: g_lo, ik_idx, il_idx
2213
    use mp, only: broadcast
2214
    use constants, only: zi
2215
    use array_utils, only: copy
2216
    use warning_helpers, only: is_zero
2217
    implicit none
2218
    integer :: iglo, ik, il
2219
    real :: c1, c2
2220

2221
    call broadcast (epsl)
×
2222
    call broadcast (eps)
×
2223
    call broadcast (pk)
×
2224

2225
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2226
       ik = ik_idx(g_lo,iglo)
×
2227
       il = il_idx(g_lo,iglo)
×
2228
       if (any(is_zero(vpa(-ntgrid:ntgrid-1,:,iglo)))) then
×
2229
          c1 = 0.0
×
2230
          c2 = 0.0
×
2231
       else
2232
          c2 = -akx(ik)*epsl/eps/pk &
×
2233
               *sum(delthet(-ntgrid:ntgrid-1)/bmag(-ntgrid:ntgrid-1))
×
2234
          c1 = c2/sum(delthet(-ntgrid:ntgrid-1)/vpa(-ntgrid:ntgrid-1,1,iglo))
×
2235
          c2 = c2/sum(delthet(-ntgrid:ntgrid-1)/vpa(-ntgrid:ntgrid-1,2,iglo))
×
2236
       end if
2237
       g(:,1,iglo) = -zi*akx(ik)*epsl/eps/pk*vpa(:,1,iglo)/bmag - zi*c1
×
2238
       g(:,2,iglo) = -zi*akx(ik)*epsl/eps/pk*vpa(:,2,iglo)/bmag - zi*c2
×
2239
    end do
2240
    call copy(g, gnew)
×
2241
  end subroutine ginit_test3
×
2242

2243
  !> FIXME : Add documentation  
2244
  subroutine ginit_convect
×
2245
    use dist_fn_arrays, only: g, gnew
2246
    use theta_grid, only: theta
2247
    use kt_grids, only: theta0
2248
    use gs2_layouts, only: g_lo, it_idx, ik_idx
2249
    use array_utils, only: copy
2250
    implicit none
2251
    integer :: it, ik, iglo
2252

2253
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2254
       it = it_idx(g_lo,iglo)
×
2255
       ik = ik_idx(g_lo,iglo)
×
2256
       g(:,1,iglo) = exp(cmplx(-(theta-theta0(it,ik))**2,k0*theta))
×
2257
       g(:,2,iglo) = g(:,1,iglo)
×
2258
    end do
2259
    call copy(g, gnew)
×
2260
  end subroutine ginit_convect
×
2261

2262
  !> FIXME : Add documentation  
2263
  subroutine ginit_recon3
×
2264
    use mp, only: proc0, mp_abort
2265
    use species, only: nspec, spec, has_electron_species
2266
    use theta_grid, only: ntgrid, theta
2267
    use kt_grids, only: naky, nakx => ntheta0, akx, aky, enforce_reality
2268
    use kt_grids, only: nx,ny,kperp2
2269
    use dist_fn_arrays, only: g, gnew, vpa, vperp2
2270
    use gs2_layouts, only: g_lo, ik_idx, it_idx, is_idx
2271
    use gs2_transforms, only: inverse2,transform2
2272
    use run_parameters, only: beta
2273
    use le_grids, only: integrate_moment
2274
    use dist_fn, only: gamtot, gamtot1, gamtot2, get_init_field
2275
    use constants, only: pi, zi
2276
    use file_utils, only: error_unit, open_output_file, close_output_file
2277
    use ran, only: ranf
2278
    use array_utils, only: copy
2279
    use warning_helpers, only: not_exactly_equal, is_not_zero, is_zero
2280
    implicit none
2281
    integer, parameter :: ncnt_mom_coeff=8
2282
    real, dimension(:, :, :, :), allocatable :: mom_coeff
×
2283
    real, dimension(:, :, :), allocatable :: mom_shift_para, mom_shift_perp
×
2284
    real :: bsq
2285
    integer :: iglo, ig, ik, it, is, i, j
2286

2287
    ! nkxyz and ukxyz determine profiles in kx-ky plane
2288
    ! nkxyz is for N, T, and ukxyz is for U
2289
    ! [do not control amplitude by these variables]
2290
    complex :: nkxyz(-ntgrid:ntgrid,nakx,naky)
×
2291
    complex :: ukxyz(-ntgrid:ntgrid,nakx,naky)
×
2292
    complex :: nkxyz_eq(-ntgrid:ntgrid,nakx,naky)
×
2293
    complex :: ukxyz_eq(-ntgrid:ntgrid,nakx,naky)
×
2294
    complex, allocatable :: g_eq(:,:,:)
×
2295

2296
    ! equilibrium and perturbation
2297
    complex :: nkxy_eq(nakx,naky), ukxy_eq(nakx,naky)
×
2298

2299
    ! *fac determine z profile
2300
    ! [do not control amplitude by these variables]
2301
    real :: dfac(-ntgrid:ntgrid), ufac(-ntgrid:ntgrid)
×
2302
    real :: tparfac(-ntgrid:ntgrid), tperpfac(-ntgrid:ntgrid)
×
2303
    real :: ct(-ntgrid:ntgrid), st(-ntgrid:ntgrid)
×
2304
    real :: c2t(-ntgrid:ntgrid), s2t(-ntgrid:ntgrid)
×
2305

2306
    ! normalization
2307
    real :: fac
2308
    real, allocatable :: nnrm(:,:,:),unrm(:,:,:)
×
2309
    real, allocatable :: tparanrm(:,:,:),tperpnrm(:,:,:)
×
2310

2311
    real :: check(3), current
2312
    character (len=2) :: cfit
2313
    complex, allocatable :: phi(:,:,:), apar(:,:,:), bpar(:,:,:)
×
2314
    real :: save_dens0, save_tperp0, save_u0, ratio
2315

2316
    ! real space profile to be Fourier transformed
2317
    real :: xx,dx,lx,ly
2318
    integer, parameter :: nfxp=2**10
2319
    integer :: nfx
2320
    real, allocatable :: nxy(:,:), uxy(:,:)
×
2321
    real, allocatable :: phixy(:,:,:), aparxy(:,:,:), bparxy(:,:,:)
×
2322

2323
    complex, allocatable :: by(:,:,:)
×
2324
    real, allocatable :: byxy(:,:,:)
×
2325
    integer :: nnx, nny, unit
2326
    real :: xmax, bymax, xa, xl1, xl2, fmin, fmax, a, b
2327

2328
    if(debug.and.proc0) write(6,*) 'Initialization recon3'
2329

2330
    cfit = 'A0'
×
2331
    check = 0
×
2332
    current = 0
×
2333
    nfx = nfxp
×
2334
    if (nfxp < nx) nfx=nx
×
2335

2336
    !! adjust input parameters to kill initial field if wanted
2337
    if(debug.and.proc0) write(6,*) 'check parameters'
2338

2339
    do is=1,nspec
×
2340
       if(adj_spec == is) cycle
×
2341
       check(1)=check(1)+spec(is)%z*spec(is)%dens*spec(is)%dens0
×
2342
       check(2)=check(2)+spec(is)%dens*spec(is)%temp* &
×
2343
            & (spec(is)%dens0+spec(is)%tperp0)
×
2344
       check(3)=check(3)+spec(is)%z*spec(is)%dens*spec(is)%stm*spec(is)%u0
×
2345
    end do
2346

2347
    if(adj_spec == 0) then
×
2348
       ! just warn if fields don't satisfy given conditions
2349
       if(null_phi .and. null_bpar) then
×
2350
          if (is_not_zero(sum(check(1:2)))) then
×
2351
             if(proc0) write(6,'(a)') 'WARNING: finite Phi or Bpar in initial condition'
×
2352
          endif
2353
       else if(null_bpar .and. .not. null_phi) then
×
2354
          ratio=gamtot1(0,eq_mode_n+1,1)/gamtot(0,eq_mode_n+1,1)
×
2355
          if (not_exactly_equal(check(1)/check(2), ratio)) then
×
2356
             if(proc0) write(6,'(a)') 'WARNING: finite Bpar in initial condition'
×
2357
          endif
2358
       else if(null_phi .and. .not. null_bpar) then
×
2359
          ratio=-(2.*gamtot2(0,eq_mode_n+1,1)+2./beta) &
×
2360
               & /gamtot1(0,eq_mode_n+1,1)
×
2361
          if (not_exactly_equal(check(1)/check(2), ratio)) then
×
2362
             if (proc0) write(6,'(a)') 'WARNING: finite Bpar in initial condition'
×
2363
          endif
2364
       endif
2365
       if (null_apar) then
×
2366
          if (is_not_zero(check(3))) then
×
2367
             if (proc0) write(6,'(a)') 'WARNING: finite Apar in initial condition'
×
2368
          end if
2369
       end if
2370
    else
2371
       ! adjust input parameter to satisfy given conditions
2372
       if (null_phi .and. null_bpar) then
×
2373
          save_dens0=spec(adj_spec)%dens0
×
2374
          save_tperp0=spec(adj_spec)%tperp0
×
2375
          spec(adj_spec)%dens0=-check(1)/(spec(adj_spec)%z*spec(adj_spec)%dens)
×
2376
          spec(adj_spec)%tperp0=-spec(adj_spec)%dens0 &
×
2377
               & -check(2)/(spec(adj_spec)%dens*spec(adj_spec)%temp)
×
2378

2379
          if (not_exactly_equal(spec(adj_spec)%dens0, save_dens0)) then
×
2380
             if (proc0) write(6,'(a,i0,a,f10.2,a)') &
×
2381
                  & 'WARNING: Initial density of spec=', spec(adj_spec)%type, &
×
2382
                  & ' is adjusted to ', spec(adj_spec)%dens0, &
×
2383
                  & ' to kill Phi and Bpar'
×
2384
          endif
2385
          if (not_exactly_equal(spec(adj_spec)%tperp0, save_tperp0)) then
×
2386
             if (proc0) write(6,'(a,i0,a,f10.2,a)') &
×
2387
                  & 'WARNING: Initial Tperp of spec=', spec(adj_spec)%type, &
×
2388
                  & ' is adjusted to ', spec(adj_spec)%tperp0, &
×
2389
                  & ' to kill Phi and Bpar'
×
2390
          endif
2391
       else if(null_bpar .and. .not. null_phi .and. eq_type=='sinusoidal') then
×
2392
          save_tperp0=spec(adj_spec)%tperp0
×
2393
          check(1)=check(1)+ &
2394
               & spec(adj_spec)%z*spec(adj_spec)%dens*spec(adj_spec)%dens0
×
2395
          ratio=gamtot1(0,eq_mode_n+1,1)/gamtot(0,eq_mode_n+1,1)
×
2396

2397
          spec(adj_spec)%tperp0=(-check(1)*ratio-check(2)) &
×
2398
               & /(spec(adj_spec)%dens*spec(adj_spec)%temp) &
×
2399
               & -spec(adj_spec)%dens0
×
2400
          if (not_exactly_equal(spec(adj_spec)%tperp0, save_tperp0)) then
×
2401
             if (proc0) write(6,'(a,i0,a,f10.2,a)') &
×
2402
                  & 'WARNING: Initial Tperp of spec=', spec(adj_spec)%type, &
×
2403
                  & ' is adjusted to ', spec(adj_spec)%tperp0, &
×
2404
                  & ' to kill Bpar'
×
2405
          endif
2406
       else if(null_phi .and. .not. null_bpar .and. eq_type=='sinusoidal') then
×
2407
          save_tperp0=spec(adj_spec)%tperp0
×
2408
          check(1)=check(1)+ &
2409
               & spec(adj_spec)%z*spec(adj_spec)%dens*spec(adj_spec)%dens0
×
2410
          ratio=-(2.*gamtot2(0,eq_mode_n+1,1)+2./beta) &
×
2411
               & /gamtot1(0,eq_mode_n+1,1)
×
2412

2413
          spec(adj_spec)%tperp0=(-check(1)*ratio-check(2)) &
×
2414
               & /(spec(adj_spec)%dens*spec(adj_spec)%temp) &
×
2415
               & -spec(adj_spec)%dens0
×
2416

2417
          if (not_exactly_equal(spec(adj_spec)%tperp0, save_tperp0)) then
×
2418
             if (proc0) write(6,'(a,i0,a,f10.2,a)') &
×
2419
                  & 'WARNING: Initial Tperp of spec=', spec(adj_spec)%type, &
×
2420
                  & ' is adjusted to ', spec(adj_spec)%tperp0, &
×
2421
                  & ' to kill Phi'
×
2422
          endif
2423
       endif
2424

2425
       if (null_apar) then
×
2426
          save_u0=spec(adj_spec)%u0
×
2427
          spec(adj_spec)%u0=-check(3)/ &
×
2428
               & (spec(adj_spec)%z*spec(adj_spec)%dens*spec(adj_spec)%stm)
×
2429
          if (not_exactly_equal(spec(adj_spec)%u0, save_u0)) then
×
2430
             if (proc0) write(6,'(a,i0,a,f10.2,a)') &
×
2431
                  & 'WARNING: Initial U of spec=', spec(adj_spec)%type, &
×
2432
                  & ' is adjusted to ', spec(adj_spec)%u0, &
×
2433
                  & ' to kill Apar'
×
2434
          endif
2435
       endif
2436
    endif
2437

2438
    !! initialize
2439
    if(debug.and.proc0) write(6,*) 'initialize variable'
2440
    nkxyz(-ntgrid:ntgrid,1:nakx,1:naky)=cmplx(0.,0.)
×
2441
    ukxyz(-ntgrid:ntgrid,1:nakx,1:naky)=cmplx(0.,0.)
×
2442
    nkxyz_eq(-ntgrid:ntgrid,1:nakx,1:naky)=cmplx(0.,0.)
×
2443
    ukxyz_eq(-ntgrid:ntgrid,1:nakx,1:naky)=cmplx(0.,0.)
×
2444

2445
    nkxy_eq(1:nakx,1:naky)=cmplx(0.,0.)
×
2446
    ukxy_eq(1:nakx,1:naky)=cmplx(0.,0.)
×
2447

2448
    dfac(-ntgrid:ntgrid)=1.
×
2449
    ufac(-ntgrid:ntgrid)=1.
×
2450
    tparfac(-ntgrid:ntgrid)=1.
×
2451
    tperpfac(-ntgrid:ntgrid)=1.
×
2452

2453
    !! equilibrium
2454
    if (is_not_zero(phiinit0)) then
×
2455
       if (nakx==1 .and. naky==1) then ! grid_option = single case
×
2456
          nkxy_eq(1,1)=cmplx(.5,0.)
×
2457
          ukxy_eq(1,1)=cmplx(.5,0.)
×
2458
       else
2459
          if (debug .and. proc0) write(6,*) 'set equilibrium profile'
2460
          allocate(nxy(nfx,ny),uxy(nfx,ny))
×
2461
          lx=2.*pi/(akx(2)-akx(1)); ly=2.*pi/(aky(2)-aky(1))
×
2462
          dx=lx/nfx
×
2463
          ! if width is negative, it gives the ratio to the box size
2464
          if(prof_width < 0. ) prof_width=-prof_width*lx
×
2465
          select case (eq_type)
×
2466
          case ('sinusoidal')
2467
             ! this gives n,Tpara,Tperp \propto cos^2 (2 pi/Lx)
2468
             ! nxy(eq_mode1(1),eq_mode1(2))=cmplx(.25, 0.)
2469
             ! this gives Apara \propto cos(2 pi/Lx), By \propto sin(2 pi x/Lx)
2470
             ! uxy(eq_mode2(1),eq_mode2(2))=cmplx(.5, 0.)
2471
             do it=1,nfx
×
2472
                xx=dx*(it-1)
×
2473
                nxy(it,1:ny)=0.
×
2474
                uxy(it,1:ny)=cos(2.*pi/lx*xx*eq_mode_u)
×
2475
             end do
2476
          case ('porcelli')
2477
             do it=1,nfx
×
2478
                xx=dx*(it-1)
×
2479
                nxy(it,1:ny)=0.
×
2480
                uxy(it,1:ny)=1./cosh((xx-.5*lx)/prof_width)**2 &
×
2481
                     & * (tanh(2.*pi/lx*xx)**2+tanh(2.*pi/lx*(xx-lx))**2 &
2482
                     & - tanh(2.*pi)**2) / (2.*tanh(pi)**2-tanh(2.*pi)**2)
×
2483
             end do
2484
          case ('doubleharris')
2485
             do it=1,nfx
×
2486
                fmin=tanh(.75*lx/prof_width)-tanh(.25*lx/prof_width)
×
2487
                fmax=2.*tanh(.25*lx/prof_width)
×
2488
                xx=dx*(it-1)
×
2489
                nxy(it,1:ny)=0.
×
2490
                uxy(it,1:ny)= 2.*( &
×
2491
                     & tanh((xx-.25*lx)/prof_width) - &
2492
                     & tanh((xx-.75*lx)/prof_width) - fmin)/(fmax-fmin)-1.
×
2493
             end do
2494
          case default
2495
             if(proc0) write(error_unit(),'(2a)') &
×
2496
                  & 'ERROR: Invalid equilibrium type', eq_type
×
2497
             call mp_abort('Invalid equilibrium type')
×
2498
          end select
2499
          ! subtract (0,0) mode
2500
          ! since it (constant part of potential) does nothing
2501
          do ik=1,ny
×
2502
             uxy(1:nfx,ik)=uxy(1:nfx,ik) &
×
2503
                  - sum(uxy(1:nfx,ik))/nfx
×
2504
          end do
2505
          call inverse2(nxy, nkxy_eq, ny, nfx)
×
2506
          call inverse2(uxy, ukxy_eq, ny, nfx)
×
2507
          deallocate(nxy,uxy)
×
2508
       endif
2509
    endif
2510

2511
    do ig = -ntgrid, ntgrid
×
2512
       nkxyz(ig,1:nakx,1:naky) = phiinit0*nkxy_eq(1:nakx,1:naky)
×
2513
       ukxyz(ig,1:nakx,1:naky) = phiinit0*ukxy_eq(1:nakx,1:naky)
×
2514
    end do
2515
    if(.not.(nakx==1 .and. naky==1)) then ! grid_option /= single case
×
2516
       nkxyz(-ntgrid:ntgrid,1,1)=cmplx(0.,0.)
×
2517
       ukxyz(-ntgrid:ntgrid,1,1)=cmplx(0.,0.)
×
2518
    endif
2519

2520
    !! save equilibrium profile
2521
    nkxyz_eq(-ntgrid:ntgrid,1:nakx,1:naky)= &
×
2522
         & nkxyz(-ntgrid:ntgrid,1:nakx,1:naky)
×
2523
    ukxyz_eq(-ntgrid:ntgrid,1:nakx,1:naky)= &
×
2524
         & ukxyz(-ntgrid:ntgrid,1:nakx,1:naky)
×
2525

2526
    !! perturbation
2527
    if (is_not_zero(phiinit)) then
×
2528
       if (debug.and.proc0) write(6,*) 'set perturbation profile'
2529
       do j = 1, 3
×
2530
          if(ikkk(j)==0) ukxy_pt(j)=.5*ukxy_pt(j) !reality
×
2531
          ik = ikkk(j)+1
×
2532
          if(ittt(j) >= 0) then
×
2533
             it = ittt(j)+1
×
2534
          else
2535
             it = nakx + ittt(j) + 1
×
2536
          endif
2537
          do ig = -ntgrid, ntgrid
×
2538
             ukxyz(ig,it,ik) = ukxyz(ig,it,ik) + phiinit*ukxy_pt(j)
×
2539
          end do
2540
       end do
2541
    endif
2542

2543
    if (is_not_zero(phiinit_rand)) then
×
2544
       do it = 1, nakx
×
2545
          do ik = 1, naky
×
2546
             a = ranf()-0.5
×
2547
             b = ranf()-0.5
×
2548
             ukxyz(:,it,ik) = ukxyz(:,it,ik) + phiinit_rand*cmplx(a,b)
×
2549
          end do
2550
       end do
2551
    end if
2552

2553
    if (debug.and.proc0) write(6,*) 'set reality condition'
2554
    if (enforce_reality) then
×
2555
       call apply_reality(nkxyz)
×
2556
       call apply_reality(ukxyz)
×
2557
       call apply_reality(nkxyz_eq)
×
2558
       call apply_reality(ukxyz_eq)
×
2559
    end if
2560

2561
    !! parallel profile
2562
    if(debug.and.proc0) write(6,*) 'set parallel profile'
2563
    if (even) then
×
2564
       ct = cos(theta)
×
2565
       st = sin(theta)
×
2566

2567
       c2t = cos(2.*theta)
×
2568
       s2t = sin(2.*theta)
×
2569
    else
2570
       ct = sin(theta)
×
2571
       st = cos(theta)
×
2572

2573
       c2t = sin(2.*theta)
×
2574
       s2t = cos(2.*theta)
×
2575
    end if
2576

2577
    dfac     = dfac     + den1   * ct + den2   * c2t
×
2578
    ufac     = ufac     + upar1  * st + upar2  * s2t
×
2579
    tparfac  = tparfac  + tpar1  * ct + tpar2  * c2t
×
2580
    tperpfac = tperpfac + tperp1 * ct + tperp2 * c2t
×
2581

2582
    !! normalization
2583
    if (debug .and. proc0) write(6,*) 'normalization'
2584
    if (is_not_zero(b0)) then
×
2585
       if (.not.(nakx==1 .and. naky==1)) then ! grid_option /= single case
×
2586
          if (eq_type == 'porcelli') then
×
2587
             xmax=.5*prof_width*log(2.+sqrt(3.))+.5*lx
×
2588
             xmax=get_xmax(xmax)
×
2589
             xa=(xmax-.5*lx)/prof_width
×
2590
             xl1=2.*pi/lx*xmax; xl2=xl1-2.*pi
×
2591
             bymax=(-2./prof_width*sinh(xa)/cosh(xa)**3* &
2592
                  & (tanh(xl1)**2+tanh(xl2)**2-tanh(2.*pi)**2) &
2593
                  & + 1./cosh(xa)**2*4.*pi/lx* &
2594
                  & (sinh(xl1)/cosh(xl1)**3+sinh(xl2)/cosh(xl2)**3) ) &
2595
                  & / (2.*tanh(pi)**2-tanh(2.*pi)**2)
×
2596
          else if(eq_type == 'doubleharris') then
×
2597
             bymax=2.*tanh(.5*lx/prof_width)**2/(prof_width*(fmax-fmin))
×
2598
          else
2599
             bymax=akx(eq_mode_u+1)
×
2600
          endif
2601
       else
2602
          bymax=sqrt(kperp2(0,1,1))
×
2603
       endif
2604
       a0 = b0/abs(bymax)
×
2605
       cfit='B0'
×
2606
    endif
2607

2608
    allocate(nnrm(nakx,naky,nspec),unrm(nakx,naky,nspec))
×
2609
    allocate(tparanrm(nakx,naky,nspec),tperpnrm(nakx,naky,nspec))
×
2610

2611
    if(.not.allocated(mom_coeff)) allocate(mom_coeff(nakx,naky,nspec,ncnt_mom_coeff))
×
2612
    if(.not.allocated(mom_shift_para)) allocate(mom_shift_para(nakx,naky,nspec))
×
2613
    if(.not.allocated(mom_shift_perp)) allocate(mom_shift_perp(nakx,naky,nspec))
×
2614

2615
    do it=1,nakx
×
2616
       do ik=1,naky
×
2617
          do is=1,nspec
×
2618
             bsq=.25*spec(is)%smz**2*kperp2(0,it,ik)
×
2619
             mom_coeff(it,ik,is,1) = exp(-bsq)
×
2620
             mom_coeff(it,ik,is,2) = exp(-bsq) *.5
×
2621
             mom_coeff(it,ik,is,3) = exp(-bsq) *(1.-bsq)
×
2622
             mom_coeff(it,ik,is,4) = exp(-bsq) *.75
×
2623
             mom_coeff(it,ik,is,5) = exp(-bsq) *(1.-bsq)*.5
×
2624
             mom_coeff(it,ik,is,6) = exp(-bsq) *.5
×
2625
             mom_coeff(it,ik,is,7) = exp(-bsq) *.25
×
2626
             mom_coeff(it,ik,is,8) = exp(-bsq) *(1.-.5*bsq)
×
2627
          end do
2628
       end do
2629
    end do
2630
    mom_shift_para=mom_coeff(:,:,:,2)/mom_coeff(:,:,:,1)
×
2631
    mom_shift_perp=mom_coeff(:,:,:,3)/mom_coeff(:,:,:,1)
×
2632

2633
    do is=1,nspec
×
2634
       nnrm(:,:,is)=mom_coeff(:,:,is,1)
×
2635
       unrm(:,:,is)=2.*mom_coeff(:,:,is,2)
×
2636
       tparanrm(:,:,is)=2.*(mom_coeff(:,:,is,4)- &
×
2637
            & 2.*mom_coeff(:,:,is,2)*mom_shift_para(:,:,is))
×
2638
       tperpnrm(:,:,is)=2.*(mom_coeff(:,:,is,8)- &
×
2639
            & mom_coeff(:,:,is,6)*mom_shift_perp(:,:,is))
×
2640

2641
       if (is_not_zero(a0)) then
×
2642
          ! rescale parallel momentum to obtain a given amplitude of Apar
2643
          current=sum(spec(1:nspec)%z*spec(1:nspec)%dens &
×
2644
               & *spec(1:nspec)%stm*spec(1:nspec)%u0)
×
2645
          if (is_zero(current)) then
×
2646
             if (proc0) write(error_unit(),'(a)') &
×
2647
                  & 'ERROR in init_g: invalid input a0, u0'
×
2648
             call mp_abort('invalid input a0, u0')
×
2649
          end if
2650
          do it=1,nakx
×
2651
             do ik=1,naky
×
2652
                if(is_not_zero(cabs(ukxyz(0,it,ik))) .and. is_not_zero(spec(is)%u0)) then
×
2653
                   fac=2.*beta*current/kperp2(0,it,ik)/a0
×
2654
                   unrm(it,ik,is)=unrm(it,ik,is)*fac
×
2655
                   if(proc0) write(6,'(a,a2,a,3(i3,1x),f20.12)') &
×
2656
                        & 'INFO: u0 is rescaled to fit ',cfit,' input', &
×
2657
                        & it,ik,is,spec(is)%u0/fac
×
2658
                end if
2659
             end do
2660
          end do
2661
       end if
2662
    end do
2663

2664
    if (debug .and. proc0) write(6,*) 'calculate g'
2665
    allocate(g_eq(-ntgrid:ntgrid,2,g_lo%llim_proc:g_lo%ulim_alloc))
×
2666
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2667
       ik = ik_idx(g_lo,iglo)
×
2668
       it = it_idx(g_lo,iglo)
×
2669
       is = is_idx(g_lo,iglo)
×
2670

2671
       g(:,1,iglo) = ( &
×
2672
            & ( dfac*spec(is)%dens0 / nnrm(it,ik,is) &
×
2673
            & + tparfac*spec(is)%tpar0 / tparanrm(it,ik,is) &
×
2674
            & * (vpa(:,1,iglo)**2-mom_shift_para(it,ik,is)) &
×
2675
            & + tperpfac*spec(is)%tperp0 / tperpnrm(it,ik,is) &
×
2676
            & * (vperp2(:,iglo)-mom_shift_perp(it,ik,is)) &
×
2677
            & ) * nkxyz(:,it,ik) &
×
2678
            & + ufac*2.*vpa(:,1,iglo)*spec(is)%u0 / unrm(it,ik,is) &
×
2679
            & * ukxyz(:,it,ik) &
×
2680
            )
×
2681
       g(:,2,iglo) = ( &
×
2682
            & ( dfac*spec(is)%dens0 / nnrm(it,ik,is) &
×
2683
            & + tparfac*spec(is)%tpar0 / tparanrm(it,ik,is) &
×
2684
            & * (vpa(:,2,iglo)**2-mom_shift_para(it,ik,is)) &
×
2685
            & + tperpfac*spec(is)%tperp0 / tperpnrm(it,ik,is) &
×
2686
            & * (vperp2(:,iglo)-mom_shift_perp(it,ik,is)) &
×
2687
            & ) * nkxyz(:,it,ik) &
×
2688
            & + ufac*2.*vpa(:,2,iglo)*spec(is)%u0 / unrm(it,ik,is) &
×
2689
            & * ukxyz(:,it,ik) &
×
2690
            )
×
2691

2692
       g_eq(:,1,iglo) = ( &
×
2693
            & ( dfac*spec(is)%dens0 / nnrm(it,ik,is) &
×
2694
            & + tparfac*spec(is)%tpar0 / tparanrm(it,ik,is) &
×
2695
            & * (vpa(:,1,iglo)**2-mom_shift_para(it,ik,is)) &
×
2696
            & + tperpfac*spec(is)%tperp0 / tperpnrm(it,ik,is) &
×
2697
            & * (vperp2(:,iglo)-mom_shift_perp(it,ik,is)) &
×
2698
            & ) * nkxyz_eq(:,it,ik) &
×
2699
            & + ufac*2.*vpa(:,1,iglo)*spec(is)%u0 / unrm(it,ik,is) &
×
2700
            & * ukxyz_eq(:,it,ik) &
×
2701
            )
×
2702
       g_eq(:,2,iglo) = ( &
×
2703
            & ( dfac*spec(is)%dens0 / nnrm(it,ik,is) &
×
2704
            & + tparfac*spec(is)%tpar0 / tparanrm(it,ik,is) &
×
2705
            & * (vpa(:,2,iglo)**2-mom_shift_para(it,ik,is)) &
×
2706
            & + tperpfac*spec(is)%tperp0 / tperpnrm(it,ik,is) &
×
2707
            & * (vperp2(:,iglo)-mom_shift_perp(it,ik,is)) &
×
2708
            & ) * nkxyz_eq(:,it,ik) &
×
2709
            & + ufac*2.*vpa(:,2,iglo)*spec(is)%u0 / unrm(it,ik,is) &
×
2710
            & * ukxyz_eq(:,it,ik) &
×
2711
            )
×
2712
    end do
2713

2714
    deallocate(nnrm,unrm,tparanrm,tperpnrm)
×
2715
    deallocate(g_eq)
×
2716

2717
    if(allocated(mom_coeff)) deallocate(mom_coeff)
×
2718
    if(allocated(mom_shift_para)) deallocate(mom_shift_para)
×
2719
    if(allocated(mom_shift_perp)) deallocate(mom_shift_perp)
×
2720

2721
    ! now store the actual g in gnew
2722
    call copy(g, gnew)
×
2723

2724
    !! check
2725
    if(debug.and.proc0) write(6,*) 'check'
2726
    if(input_check_recon) then
×
2727

2728
       allocate(phi(-ntgrid:ntgrid,nakx,naky))
×
2729
       allocate(apar(-ntgrid:ntgrid,nakx,naky))
×
2730
       allocate(bpar(-ntgrid:ntgrid,nakx,naky))
×
2731

2732
       call get_init_field(phi,apar,bpar)
×
2733

2734
       if(nakx==1 .and. naky==1) then ! grid_option = single case
×
2735
          if(proc0) then
×
2736
             write(6,'(" phi  = ",2e25.17)') &
2737
                  & real(phi (0,1,1)),aimag(phi (0,1,1))
×
2738
             write(6,'(" apar = ",2e25.17)') &
2739
                  & real(apar(0,1,1)),aimag(apar(0,1,1))
×
2740
             write(6,'(" bpar = ",2e25.17)') &
2741
                  & real(bpar(0,1,1)),aimag(bpar(0,1,1))
×
2742
          endif
2743
       else
2744
          if(nx>nakx) then
×
2745
             nnx=nx
×
2746
          else ! nx=nakx=1
2747
             nnx=(3*nakx+1)/2
×
2748
          endif
2749
          if(ny>naky) then
×
2750
             nny=ny
×
2751
          else ! ny=naky=1
2752
             nny=3*naky
×
2753
          endif
2754
          allocate(phixy(nnx,nny,-ntgrid:ntgrid))
×
2755
          allocate(aparxy(nnx,nny,-ntgrid:ntgrid))
×
2756
          allocate(bparxy(nnx,nny,-ntgrid:ntgrid))
×
2757

2758
          allocate(by(-ntgrid:ntgrid,nakx,naky))
×
2759
          allocate(byxy(nnx,nny,-ntgrid:ntgrid))
×
2760

2761
          call transform2(phi,phixy,nny,nnx)
×
2762
          call transform2(apar,aparxy,nny,nnx)
×
2763
          call transform2(bpar,bparxy,nny,nnx)
×
2764
          do it=1,nakx
×
2765
             by(:,it,:)=-zi*akx(it)*apar(:,it,:)
×
2766
          end do
2767
          call transform2(by,byxy,nny,nnx)
×
2768

2769
          if(proc0) then
×
2770
             write(6,'(" phi : mode=",2i4," amp=",e25.17)') &
2771
                  & eq_mode_n,0, &
×
2772
                  & real(phi (0,eq_mode_n+1,1))
×
2773
             write(6,'(" apar: mode=",2i4," amp=",e25.17)') &
2774
                  & eq_mode_u,0, &
×
2775
                  & real(apar(0,eq_mode_u+1,1))
×
2776
             write(6,'(" bpar: mode=",2i4," amp=",e25.17)') &
2777
                  & eq_mode_n,0, &
×
2778
                  & real(bpar(0,eq_mode_n+1,1))
×
2779

2780
             call open_output_file(unit, '.check_field.dat')
×
2781
             write(unit,'(a1,1x,5a20)') '#','x','y','phi','apar','bpar','by'
×
2782
             do it=1,nx+1
×
2783
                i=mod(it-1,nx)+1
×
2784
                do ik=1,ny+1
×
2785
                   j=mod(ik-1,ny)+1
×
2786
                   write(unit,'(2x,6d20.12)') lx/nx*(it-1),ly/ny*(ik-1), &
×
2787
                        & phixy(i,j,0),aparxy(i,j,0),bparxy(i,j,0),byxy(i,j,0)
×
2788
                end do
2789
                write(unit,*)
×
2790
             end do
2791
             call close_output_file(unit)
×
2792
          endif
2793
       endif
2794
    endif
2795

2796
    deallocate(phi,apar,bpar)
×
2797
    if(allocated(phixy)) deallocate(phixy)
×
2798
    if(allocated(aparxy)) deallocate(aparxy)
×
2799
    if(allocated(bparxy)) deallocate(bparxy)
×
2800
    if(allocated(by)) deallocate(by)
×
2801
    if(allocated(byxy)) deallocate(byxy)
×
2802

2803
  contains
2804
    !> FIXME : Add documentation    
2805
    function get_xmax(xguess) result(xsol)
×
2806
      implicit none
2807
      real :: xsol
2808
      real, intent(in) :: xguess
2809
      real, parameter :: tol=1.e-20
2810
      real :: xold
2811
      integer :: i
2812
      integer, parameter :: itmax = 1000
2813
      xold=xguess
×
2814
      do i=1,itmax
×
2815
         xsol=xold-f(xold)/fprime(xold)
×
2816
         if(abs(xsol-xold) > tol) then
×
2817
            xold=xsol
×
2818
         else
2819
            return
×
2820
         endif
2821
      end do
2822
    end function get_xmax
×
2823

2824
    !> FIXME : Add documentation    
2825
    function f(x)
×
2826
      implicit none
2827
      real :: f
2828
      real, intent(in) :: x
2829
      real :: xa, xl1, xl2
2830
      xa=(x-.5*lx)/prof_width
×
2831
      xl1=2.*pi/lx*x
×
2832
      xl2=xl1-2.*pi
×
2833

2834
      f= &
2835
           & 2./prof_width**2*(cosh(2.*xa)-2.)/cosh(xa)**4* & ! f''
2836
           & (tanh(xl1)**2+tanh(xl2)**2-tanh(2.*pi)**2) & ! g
2837
           & + 2. * &
2838
           & (-2./prof_width)*sinh(xa)/cosh(xa)**3* & ! f'
2839
           & 4.*pi/lx*(sinh(xl1)/cosh(xl1)**3+sinh(xl2)/cosh(xl2)**3) & ! g'
2840
           & + &
2841
           & 1./cosh(xa)**2* & ! f
2842
           & 8.*(pi/lx)**2*((2.-cosh(2.*xl1))/cosh(xl1)**4 & ! g''
2843
           &               +(2.-cosh(2.*xl2))/cosh(xl2)**4)
×
2844

2845
    end function f
×
2846

2847
    !> FIXME : Add documentation
2848
    function fprime(x)
×
2849
      implicit none
2850
      real :: fprime
2851
      real, intent(in) :: x
2852
      real :: xa, xl1, xl2
2853
      xa=(x-.5*lx)/prof_width
×
2854
      xl1=2.*pi/lx*x
×
2855
      xl2=xl1-2.*pi
×
2856

2857
      fprime = &
2858
           & 8./prof_width**3*(2.*sinh(xa)-sinh(xa)**3)/cosh(xa)**5* & ! f''' 
2859
           & (tanh(xl1)**2+tanh(xl2)**2-tanh(2.*pi)**2) & ! g
2860
           & + 3. * &
2861
           & 2./prof_width**2*(cosh(2.*xa)-2.)/cosh(xa)**4* & ! f''
2862
           & 4.*pi/lx*(sinh(xl1)/cosh(xl1)**3+sinh(xl2)/cosh(xl2)**3) & ! g'
2863
           & + 3. * &
2864
           & (-2./prof_width)*sinh(xa)/cosh(xa)**3* & ! f'
2865
           & 8.*(pi/lx)**2*((2.-cosh(2.*xl1))/cosh(xl1)**4 & ! g''
2866
           &               +(2.-cosh(2.*xl2))/cosh(xl2)**4) &
2867
           & + &
2868
           & 1./cosh(xa)**2* & ! f
2869
           & (-64.)*(pi/lx)**3 * ( & ! g'''
2870
           & (2.*sinh(xl1)-sinh(xl1)**3)/cosh(xl1)**5 + &
2871
           & (2.*sinh(xl2)-sinh(xl2)**3)/cosh(xl2)**5 )
×
2872
    end function fprime
×
2873

2874
  end subroutine ginit_recon3
2875

2876
  !> Restore `g` from restart files. Note that the timestep and simulation time
2877
  !> are restored by [[read_t0_from_restart_file]]
2878
  subroutine ginit_restart_many
×
2879
    use dist_fn_arrays, only: g, gnew
2880
    use fields_arrays, only: phi, apar, bpar, phinew, aparnew, bparnew
2881
    use gs2_save, only: gs2_restore
2882
    use run_parameters, only: has_phi, has_apar, has_bpar
2883
    use array_utils, only: copy, zero_array
2884
    implicit none
2885
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
2886
    call copy(g, gnew)
×
2887
    call copy(phinew, phi) ; call copy(aparnew, apar) ; call copy(bparnew, bpar)
×
2888
  end subroutine ginit_restart_many
×
2889

2890
  !> Uses the restart files written by the eigensolver. File to read is set by
2891
  !> [[init_g_knobs:restart_eig_id]]
2892
  subroutine ginit_restart_eig
×
2893
    use dist_fn_arrays, only: g, gnew
2894
    use fields_arrays, only: phi, apar, bpar, phinew, aparnew, bparnew
2895
    use gs2_save, only: gs2_restore
2896
    use run_parameters, only: has_phi, has_apar, has_bpar
2897
    use array_utils, only: copy, zero_array
2898
    implicit none
2899
    character(len=20) :: restart_unique_string
2900
    write(restart_unique_string,'(".eig_",I0)') restart_eig_id
×
2901
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar, fileopt=restart_unique_string)
×
2902
    call copy(g, gnew)
×
2903
    call copy(phinew, phi) ; call copy(aparnew, apar) ; call copy(bparnew, bpar)
×
2904
  end subroutine ginit_restart_eig
×
2905

2906
  !> Restores `g` from restart files _on top of_ a background from [[ginit_noise]].
2907
  !>
2908
  !> Note that this doesnt set `phi`, `apar`, `bpar` -- is this correct?
2909
  subroutine ginit_restart_small
×
2910
    use dist_fn_arrays, only: g, gnew
2911
    use gs2_save, only: gs2_restore
2912
    use run_parameters, only: has_phi, has_apar, has_bpar
2913
    use array_utils, only: copy, zero_array
2914
    implicit none
2915
    call ginit_noise
×
2916
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
2917
    g = g + gnew
×
2918
    call copy(g, gnew)
×
2919
  end subroutine ginit_restart_small
×
2920

2921
  !> Similar to `"small"`, restores fields from restart files _on top of_ a
2922
  !> random background.
2923
  !>
2924
  !> @Todo this starts with a reduced functionality version of ginit_noise
2925
  !> followed by ginit_restart_many (effectively). This is therefore a reduced
2926
  !> functionality version of ginit_restart_small and we can probably just drop this?
2927
  subroutine ginit_restart_smallflat
×
2928
    use gs2_save, only: gs2_restore
2929
    use species, only: spec
2930
    use theta_grid, only: ntgrid 
2931
    use kt_grids, only: naky, ntheta0, aky, enforce_reality
2932
    use le_grids, only: forbid
2933
    use dist_fn_arrays, only: g, gnew
2934
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
2935
    use run_parameters, only: has_phi, has_apar, has_bpar
2936
    use ran, only: ranf
2937
    use array_utils, only: copy, zero_array
2938
    use warning_helpers, only: is_zero
2939
    implicit none
2940
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
2941
    real :: a, b
2942
    integer :: iglo, ik, it, il, is
2943

2944
    do it = 1, ntheta0
×
2945
       do ik = 1, naky
×
2946
          a = ranf()-0.5
×
2947
          b = ranf()-0.5
×
2948
          phi(:,it,ik) = cmplx(a,b)
×
2949
       end do
2950
    end do
2951

2952
    if (naky > 1 .and. is_zero(aky(1))) phi(:,:,1) = phi(:,:,1) * zf_init
×
2953
    if (enforce_reality) call apply_reality(phi)
×
2954

2955
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
2956
       ik = ik_idx(g_lo,iglo)
×
2957
       it = it_idx(g_lo,iglo)
×
2958
       il = il_idx(g_lo,iglo)
×
2959
       is = is_idx(g_lo,iglo)
×
2960
       g(:,1,iglo) = -phi(:,it,ik)*spec(is)%z*phiinit
×
2961
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
2962
       g(:,2,iglo) = g(:,1,iglo)
×
2963
    end do
2964
    call copy(g, gnew)
×
2965

2966
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
2967
    g = g + gnew
×
2968
    call copy(g, gnew)
×
2969
  end subroutine ginit_restart_smallflat
×
2970

2971
  !> Restart but set all non-zonal components \((k_y \ne 0)\) of the potential
2972
  !> and the distribution function to 0. Noise can be added to these other
2973
  !> components by setting [[init_g_knobs:phiinit]] > 0. The size of the zonal
2974
  !> flows can be adjusted using [[init_g_knobs:zf_init]].
2975
  !>
2976
  !> Author EGH
2977
  subroutine ginit_restart_zonal_only
×
2978
    use gs2_save, only: gs2_restore
2979
    use kt_grids, only: naky, ntheta0, aky
2980
    use dist_fn_arrays, only: g, gnew
2981
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
2982
    use fields_arrays, only: phinew
2983
    use run_parameters, only: has_phi, has_apar, has_bpar
2984
    use array_utils, only: copy, zero_array
2985
    use warning_helpers, only: is_zero
2986
    implicit none
2987
    integer :: iglo, ik, it, il, is
2988

2989
    !  Load phi and g from the restart file
2990
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
2991
    
2992
    ! Set all non-zonal components of phi to 0
2993
    do it = 1, ntheta0
×
2994
       do ik = 2, naky ! Starting at 2 is the crucial bit!
×
2995
          phinew(:,it,ik) = cmplx(0.0,0.0)
×
2996
       end do
2997
    end do
2998
    
2999
    ! Allow adjustment of the size of the zonal flows via the input parameter zf_init
3000
    if (naky > 1 .and. is_zero(aky(1))) phinew(:,:,1) = phinew(:,:,1) * zf_init
×
3001
    
3002
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
3003
       ik = ik_idx(g_lo,iglo)
×
3004
       it = it_idx(g_lo,iglo)
×
3005
       il = il_idx(g_lo,iglo)
×
3006
       is = is_idx(g_lo,iglo)
×
3007
       if (ik > 1) g(:, :, iglo) = 0.0
×
3008
    end do
3009

3010
    ! If phiinit > 0, add some noise
3011
    if (phiinit >  epsilon(0.0)) then 
×
3012
      call ginit_noise
×
3013
      g = g + gnew
×
3014
    end if
3015
    call copy(g, gnew)
×
3016
  end subroutine ginit_restart_zonal_only
×
3017

3018
  !> Restart but remove the zonal flow (ky = 0) component upon restarting.
3019
  !>
3020
  !> Author: FvW (copy of EGH code)
3021
  subroutine ginit_restart_no_zonal
×
3022
    use gs2_save, only: gs2_restore
3023
    use dist_fn_arrays, only: g, gnew
3024
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
3025
    use fields_arrays, only: phinew
3026
    use run_parameters, only: has_phi, has_apar, has_bpar
3027
    use array_utils, only: copy
3028
    implicit none
3029
    integer :: iglo, ik, it, il, is
3030

3031
    !Load phi and g from the restart file
3032
    call gs2_restore (g, scale, has_phi, has_apar, has_bpar)
×
3033
    
3034
    !Set zonal component of phi to 0
3035
    phinew(:,:,1) = cmplx(0.0,0.0)
×
3036
    
3037
    !Set zonal components of g to zero using phi
3038
    
3039
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
3040
       ik = ik_idx(g_lo,iglo)
×
3041
       it = it_idx(g_lo,iglo)
×
3042
       il = il_idx(g_lo,iglo)
×
3043
       is = is_idx(g_lo,iglo)
×
3044
       if (ik == 1) g(:, :, iglo) = 0.0
×
3045
    end do
3046
    call copy(g, gnew)
×
3047
  end subroutine ginit_restart_no_zonal
×
3048

3049
  !> The stationary mode test case is a method of testing the geometry
3050
  !! implementation by initializing the distribution function in a particular way
3051
  !! For collisionless runs with ky=0, we expect the solution to be
3052
  !! time-independent (see section 3.3.1 of Ball MIT Masters thesis)
3053
  !!
3054
  !! JRB
3055
  subroutine ginit_stationary_mode
×
3056
    use species, only: spec, nspec
3057
    use theta_grid, only: ntgrid, theta, bmag, rhoc
3058
    use kt_grids, only: akx
3059
    use dist_fn_arrays, only: g, gnew, vpa, aj0
3060
    use gs2_layouts, only: g_lo, it_idx, is_idx
3061
    use geometry, only : surf, geom !< Should be Rplot from theta_grid instead of geom%Rpos?
3062
    use array_utils, only: copy
3063
    use constants, only: zi
3064
    implicit none
3065

3066
    complex, dimension (-ntgrid:ntgrid) :: phi
×
3067
    integer :: iglo
3068
    integer :: ig, ik, it, is
3069

3070
    real, dimension (-ntgrid:ntgrid) :: numeratorSum
×
3071
    real :: denominatorSum, qinp, R_geo
3072

3073
    numeratorSum(:) = 0 ; denominatorSum = 0
×
3074
    qinp = surf%q ; R_geo = surf%r_geo
×
3075
    it = 1
×
3076
    ik = 1
×
3077
    do is = 1, nspec
×
3078
      do ig = -ntgrid, ntgrid
×
3079
        numeratorSum(ig) = numeratorSum(ig) + ((spec(is)%z)**2)*spec(is)%dens*exp(-((spec(is)%mass*spec(is)%temp)/(4*(spec(is)%z)**2))*((qinp/rhoc)*akx(it)*geom%Rpos(rhoc,theta(ig)))**2)
×
3080
      end do
3081
      denominatorSum = denominatorSum + (spec(is)%z)**2*spec(is)%dens/spec(is)%temp
×
3082
    end do
3083

3084
    phi(:) = numeratorSum(:)/denominatorSum
×
3085

3086
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
3087
       it = it_idx(g_lo,iglo)
×
3088
       is = is_idx(g_lo,iglo)
×
3089

3090
       g(:,1,iglo) = spec(is)%z*exp(-zi*(qinp/rhoc)*akx(it)*vpa(:,1,iglo)*R_geo*(spec(is)%mass/(spec(is)%z*bmag(:)))) &
×
3091
                   - (spec(is)%z/spec(is)%temp)*aj0(:,iglo)*phi(:)
×
3092
       g(:,2,iglo) = spec(is)%z*exp(-zi*(qinp/rhoc)*akx(it)*vpa(:,2,iglo)*R_geo*(spec(is)%mass/(spec(is)%z*bmag(:)))) &
×
3093
                   - (spec(is)%z/spec(is)%temp)*aj0(:,iglo)*phi(:)
×
3094
    end do
3095
    call copy(g, gnew)
×
3096
  end subroutine ginit_stationary_mode
×
3097

3098
  !> Sets g to a constant value everywhere except zonal component which is 0
3099
  !> Default initial conditions for CGYRO
3100
  !>
3101
  !> if phiinit>0:
3102
  !>     g(ky!=0) = constant
3103
  !> else:
3104
  !>     g(ky!=0) = constant/n
3105
  !>
3106
  !> if zfinit!=0:
3107
  !>     g(ky==0) = constant * exp(-|kx|/max(kx))
3108
  !> else:
3109
  !>     g(ky==0) = 0
3110
  !>
3111
  !> Set by having 'ginit_option' = cgyro
3112
  !> Equivalent CGYRO parameters achieved by setting
3113
  !>    GS2   =    CGYRO
3114
  !> phiinit = AMP / sqrt(2)
3115
  !> zfinit   = AMP0 / AMP
3116
  !>
3117
  !> By default AMP0=0 and AMP=0.1 in CGYRO
3118
  !>
3119
  !> Potential issue in AMP=0 in CGYRO due to zfinit defn
3120
  !>
3121
  !> Author: BSP (copy of EGH code)
3122
  subroutine ginit_cgyro
×
3123
    use mp, only: proc0
3124
    use le_grids, only: forbid
3125
    use kt_grids, only: akx, aky
3126
    use dist_fn_arrays, only: g, gnew
3127
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx
3128
    use array_utils, only: copy
3129
    use warning_helpers, only: is_zero
3130
    implicit none
3131
    integer :: iglo
3132
    integer :: ik, it, il, in
3133
    real :: arg, kxrange
3134

3135
    kxrange = maxval(akx) - minval(akx)
×
3136

3137
    if(debug.and.proc0) write(*,*) 'Entering CGYRO def'
3138
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
3139
       ik = ik_idx(g_lo,iglo)
×
3140
       it = it_idx(g_lo,iglo)
×
3141
       il = il_idx(g_lo,iglo)
×
3142
       if (is_zero(aky(ik))) then
×
3143
          arg = abs(akx(it))/ kxrange
×
3144
          g(:,1,iglo) = zf_init * abs(phiinit) * exp(-arg)
×
3145
       else
3146
          ! Ensure we don't end up with in = 0. This shouldn't
3147
          ! be needed for flux tube (box) simulations as ik == 1
3148
          ! would correspond to the zonal mode, handled in the
3149
          ! earlier branch.
3150
          if (phiinit < 0.0 .and. ik > 1) then
×
3151
             in = ik - 1
×
3152
          else
3153
             in = 1
×
3154
          end if
3155
          g(:,1,iglo) = abs(phiinit) / in**2
×
3156
       end if
3157

3158
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
3159
       g(:,2,iglo) = g(:,1,iglo)
×
3160
    end do
3161
    call copy(g, gnew)
×
3162
  end subroutine ginit_cgyro
×
3163

3164
  !> Construct the initial condition from a sum of sine waves scaled
3165
  !> with random amplitude up to phiinit (ky > 0) or zf_init (ky ==
3166
  !> 0). Use mode numbers up to minimum of max_mode or last resolved
3167
  !> wave (i.e. ntheta/8).
3168
  !>
3169
  !> A sine wave is selected in order to ensure that the initial
3170
  !> distribution satisfies the parallel boundary conditions
3171
  !> (i.e. that either gnew or h = 0).
3172
  subroutine ginit_random_sine
×
3173
    use theta_grid, only: ntgrid, ntheta, theta
3174
    use kt_grids, only: naky, ntheta0, aky, enforce_reality, akx
3175
    use le_grids, only: forbid
3176
    use dist_fn_arrays, only: g, gnew
3177
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
3178
    use constant_random, only: init_constant_random, finish_constant_random
3179
    use mp, only: proc0, broadcast
3180
    use array_utils, only: copy, zero_array
3181
    use warning_helpers, only: is_zero
3182
    use species, only: spec
3183
    implicit none
3184
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: phi
×
3185
    real, dimension(-ntgrid:ntgrid) :: sin_theta_mode
×
3186
    real :: a, b
3187
    real, parameter :: sqrt_two = sqrt(2.0)
3188
    integer :: iglo, ik, it, il, imode, the_max_mode
3189

3190
    call zero_array(phi)
×
3191

3192
    ! Make sure the max mode is at least 1, but no bigger than the smaller
3193
    ! of the input max_mode and ntheta/8
3194
    the_max_mode = max(1, min(max_mode, ntheta/8))
×
3195

3196
    ! We choose to only initialise on proc0 and then broadcast to make
3197
    ! sure that all procs have the same values. If done on a processor
3198
    ! by processor basis, then it's possible that different processors
3199
    ! would produce different values. This could lead to a non-Maxwellian
3200
    ! perturbation (i.e. something not constant in our velocity space).
3201
    if (proc0) then
×
3202
       if (constant_random_flag) call init_constant_random
×
3203
       ! Here we go from 2*min_mode (min_mode == 1) to 2*the_max_mode
3204
       ! but then divide imode by two in order to allow us to capture
3205
       ! n + 1/2 mode numbers and hence provide an even parity
3206
       ! contribution to the initial condition.
3207
       do imode = 2, the_max_mode*2
×
3208
          sin_theta_mode = sin(imode*(theta-theta(-ntgrid))/2.0)
×
3209
          do ik = 1, naky
×
3210
             do it = 1, ntheta0
×
3211
                call set_a_and_b_uniform_random_weighting(a, b)
×
3212
                phi(:, it, ik) = phi(:, it, ik) + cmplx(a*sin_theta_mode, b*sin_theta_mode)
×
3213
             end do
3214
          end do
3215
       end do
3216
       if (constant_random_flag) call finish_constant_random
×
3217
       if (enforce_reality) call apply_reality(phi)
×
3218
    end if
3219

3220
    call broadcast(phi)
×
3221

3222
    ! Now set the distribution function from "phi".
3223
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
3224
       ik = ik_idx(g_lo, iglo)
×
3225
       it = it_idx(g_lo, iglo)
×
3226
       il = il_idx(g_lo, iglo)
×
3227
       if (is_zero(aky(ik))) then
×
3228
          g(:, 1, iglo) = zf_init * phiinit * phi(:, it, ik)
×
3229

3230
          ! Zero the ky=kx=0 mode
3231
          if (is_zero(akx(it))) g(:, 1, iglo) = 0.0
×
3232
       else
3233
          g(:, 1, iglo) = phiinit * phi(:, it, ik)
×
3234
       end if
3235
       g(:, 1, iglo) = g(:, 1, iglo) * spec(is_idx(g_lo, iglo))%z
×
3236
       where (forbid(:, il)) g(:, 1, iglo) = 0.0
×
3237
       g(:, 2, iglo) = g(:, 1, iglo)
×
3238
    end do
3239
    call copy(g, gnew)
×
3240
  contains
3241
    !> Real and imaginary weights are uniformly distributed between
3242
    !> -1/sqrt(2) and 1/sqrt(2) using either the main random number
3243
    !> generator or the constant random one.
3244
    subroutine set_a_and_b_uniform_random_weighting(a, b)
×
3245
      use ran, only: ranf
3246
      use constant_random, only: constant_ranf=>ranf
3247
      implicit none
3248
      real, intent(out) :: a, b
3249
      if (constant_random_flag) then
×
3250
         a = (constant_ranf() - 0.5)
×
3251
         b = (constant_ranf() - 0.5)
×
3252
      else
3253
         a = (ranf() - 0.5)
×
3254
         b = (ranf() - 0.5)
×
3255
      end if
3256
      a = a * sqrt_two
×
3257
      b = b * sqrt_two
×
3258
    end subroutine set_a_and_b_uniform_random_weighting
×
3259

3260
  end subroutine ginit_random_sine
3261

3262
  !> Initialise the distribution function to a constant but satisfying
3263
  !> forbidden regions. Can scale the zonal component separately as
3264
  !> usual.
3265
  subroutine ginit_constant
×
3266
    use kt_grids, only: aky, akx
3267
    use le_grids, only: forbid
3268
    use dist_fn_arrays, only: g, gnew
3269
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
3270
    use array_utils, only: copy
3271
    use warning_helpers, only: is_zero
3272
    use species, only: spec
3273
    implicit none
3274
    integer :: iglo, ik, it, il
3275

3276
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
3277
       ik = ik_idx(g_lo, iglo)
×
3278
       it = it_idx(g_lo, iglo)
×
3279
       il = il_idx(g_lo, iglo)
×
3280
       if (is_zero(aky(ik))) then
×
3281
          g(:, 1, iglo) = zf_init * phiinit
×
3282

3283
          ! Zero the ky=kx=0 mode
3284
          if (is_zero(akx(it))) g(:, 1, iglo) = 0.0
×
3285
       else
3286
          g(:, 1, iglo) = phiinit
×
3287
       end if
3288
       g(:, 1, iglo) = g(:, 1, iglo) * spec(is_idx(g_lo, iglo))%z
×
3289
       where (forbid(:, il)) g(:, 1, iglo) = 0.0
×
3290
       g(:, 2, iglo) = g(:, 1, iglo)
×
3291
    end do
3292
    call copy(g, gnew)
×
3293
  end subroutine ginit_constant
×
3294

3295
  !> Helper function for common approach to setting g from a passed phi array
3296
  subroutine set_g_from_moment_facs(g, phiinit, phi, dfac_species_weight, &
×
3297
       ufac_species_weight, use_even, do_reality)
3298
    use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, is_idx
3299
    use theta_grid, only: ntgrid, theta
3300
    use kt_grids, only: naky, ntheta0
3301
    use dist_fn_arrays, only: vpa, vperp2
3302
    use le_grids, only: forbid
3303
    use species, only: spec, nspec
3304
    use constants, only: zi
3305
    complex, dimension(-ntgrid:, :, g_lo%llim_proc:), intent(in out) :: g
3306
    real, intent(in) :: phiinit ! Shadows module level
3307
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky), intent(in out) :: phi
3308
    logical, intent(in) :: dfac_species_weight, ufac_species_weight, use_even, do_reality
3309
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky) :: odd
×
3310
    real, dimension(-ntgrid:ntgrid) :: dfac, ufac, tparfac, tperpfac, ct, st, c2t, s2t
×
3311
    integer :: iglo, ik, it, il, is
3312
    real, dimension(nspec) :: dfac_weight, ufac_weight
×
3313
    if (use_even) then
×
3314
       ct = cos(theta) ; st = sin(theta)
×
3315
       c2t = cos(2.*theta) ; s2t = sin(2.*theta)
×
3316
    else
3317
       ct = sin(theta) ; st = cos(theta)
×
3318
       c2t = sin(2.*theta) ; s2t = cos(2.*theta)
×
3319
    end if
3320

3321
    dfac     = den0   + den1 * ct + den2 * c2t
×
3322
    ufac     = upar0  + upar1* st + upar2* s2t
×
3323
    tparfac  = tpar0  + tpar1* ct + tpar2* c2t
×
3324
    tperpfac = tperp0 + tperp1*ct + tperp2*c2t
×
3325

3326
    dfac_weight = 1.0
×
3327
    if (dfac_species_weight) dfac_weight = spec%dens0
×
3328
    ufac_weight = 1.0
×
3329
    if (ufac_species_weight) ufac_weight = spec%u0
×
3330

3331
    odd = zi * phi
×
3332

3333
    ! reality condition for k_theta = 0 component:
3334
    if (do_reality) then
×
3335
       call apply_reality(phi)
×
3336
       call apply_reality(odd)
×
3337
    end if
3338

3339
    !$OMP PARALLEL DO DEFAULT(none) &
3340
    !$OMP PRIVATE(iglo, ik, it, il, is) &
3341
    !$OMP SHARED(g_lo, g, phiinit, dfac, dfac_weight, phi, &
3342
    !$OMP ufac, ufac_weight, vpa, odd, tparfac, tperpfac, vperp2, forbid) &
3343
    !$OMP SCHEDULE(static)
3344
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
3345
       ik = ik_idx(g_lo,iglo)
×
3346
       it = it_idx(g_lo,iglo)
×
3347
       il = il_idx(g_lo,iglo)
×
3348
       is = is_idx(g_lo,iglo)
×
3349

3350
       g(:,1,iglo) = phiinit* &
×
3351
            ( dfac*dfac_weight(is)                 * phi(:,it,ik) &
×
3352
            + 2*ufac*ufac_weight(is)*vpa(:,1,iglo) * odd(:,it,ik) &
×
3353
            + tparfac*(vpa(:,1,iglo)**2-0.5)       * phi(:,it,ik) &
×
3354
            +tperpfac*(vperp2(:,iglo)-1.)          * phi(:,it,ik))
×
3355
       where (forbid(:,il)) g(:,1,iglo) = 0.0
×
3356

3357
       g(:,2,iglo) = phiinit* &
×
3358
            ( dfac*dfac_weight(is)                 * phi(:,it,ik) &
×
3359
            + 2*ufac*ufac_weight(is)*vpa(:,2,iglo) * odd(:,it,ik) &
×
3360
            + tparfac*(vpa(:,2,iglo)**2-0.5)       * phi(:,it,ik) &
×
3361
            +tperpfac*(vperp2(:,iglo)-1.)          * phi(:,it,ik))
×
3362
       where (forbid(:,il)) g(:,2,iglo) = 0.0
×
3363
    end do
3364
    !$OMP END PARALLEL DO
3365
  end subroutine set_g_from_moment_facs
×
3366

3367
  !> Apply the reality condition to the zonal mode (kx = conj(-kx))
3368
  subroutine apply_reality(field)
×
3369
    use kt_grids, only: ntheta0
3370
    complex, dimension(:, :, :), intent(in out) :: field
3371
    integer :: it
3372
    !$OMP PARALLEL DO DEFAULT(none) &
3373
    !$OMP PRIVATE(it) &
3374
    !$OMP SHARED(ntheta0, field) &
3375
    !$OMP SCHEDULE(static)
3376
    do it = 1, ntheta0 / 2
×
3377
       field(:, it+(ntheta0+1)/2, 1) = conjg(field(:, (ntheta0+1)/2+1-it, 1))
×
3378
    end do
3379
    !$OMP END PARALLEL DO
3380
  end subroutine apply_reality
×
3381

3382
  subroutine do_chop_side_slice(field_slice)
×
3383
    use theta_grid, only: ntgrid
3384
    complex, dimension(-ntgrid:), intent(in out) :: field_slice
3385
    if (chop_side .and. left) field_slice(:-1) = 0.0
×
3386
    if (chop_side .and. .not. left) field_slice(1:) = 0.0
×
3387
  end subroutine do_chop_side_slice
×
3388

3389
  subroutine do_chop_side_full(field)
×
3390
    use theta_grid, only: ntgrid
3391
    complex, dimension(-ntgrid:,:,:), intent(in out) :: field
3392
    if (chop_side .and. left) field(:-1, :, :) = 0.0
×
3393
    if (chop_side .and. .not. left) field(1:, :, :) = 0.0
×
3394
  end subroutine do_chop_side_full
×
3395

3396
  !> FIXME : Add documentation
3397
  subroutine single_initial_kx(phi)
×
3398
    use theta_grid, only: ntgrid
3399
    use kt_grids, only: naky, ntheta0
3400
    use mp, only: mp_abort
3401
    implicit none
3402
    complex, dimension (-ntgrid:ntgrid,ntheta0,naky), intent(inout) :: phi
3403
    integer :: ig, ik, it
3404

3405
    if (ikx_init  < 2 .or. ikx_init > (ntheta0+1)/2) then
×
3406
      call mp_abort("The subroutine single_initial_kx should only be called when 1 < ikx_init < (ntheta0+1)/2")
×
3407
    end if
3408

3409
    do it = 1, ntheta0
×
3410
      if (it /= ikx_init) then
×
3411
         do ik = 1, naky
×
3412
            do ig = -ntgrid, ntgrid
×
3413
               phi(ig,it,ik) = 0.
×
3414
             end do
3415
         end do
3416
       end if
3417
    end do
3418
  end subroutine single_initial_kx
×
3419

3420
  !> FIXME : Add documentation
3421
  subroutine flae (g, gavg)
×
3422
    use species, only: spec, is_electron_species
3423
    use theta_grid, only: ntgrid, field_line_average
3424
    use kt_grids, only: aky
3425
    use gs2_layouts, only: g_lo, is_idx, ik_idx
3426
    use array_utils, only: zero_array
3427
    use warning_helpers, only: is_not_zero
3428
    complex, dimension (-ntgrid:,:,g_lo%llim_proc:), intent (in) :: g
3429
    complex, dimension (-ntgrid:,:,g_lo%llim_proc:), intent (out) :: gavg
3430
    integer :: iglo
3431
    call zero_array(gavg)
×
3432

3433
    !$OMP PARALLEL DO DEFAULT(NONE)&
3434
    !$OMP PRIVATE(iglo) &
3435
    !$OMP SHARED(g_lo, g, gavg, spec, aky) &
3436
    !$OMP SCHEDULE(static)
3437
    do iglo = g_lo%llim_proc, g_lo%ulim_proc
×
3438
       if (.not. is_electron_species(spec(is_idx(g_lo, iglo)))) cycle
×
3439
       if (is_not_zero(aky(ik_idx(g_lo, iglo)))) cycle
×
3440
       gavg(:, 1, iglo) = field_line_average(g(:, 1, iglo))
×
3441
       gavg(:, 2, iglo) = field_line_average(g(:, 2, iglo))
×
3442
    end do
3443
    !$OMP END PARALLEL DO
3444
  end subroutine flae
×
3445

3446
  !> FIXME : Add documentation    
3447
  subroutine finish_init_g
12✔
3448
    implicit none
3449
    initialized = .false.
12✔
3450
  end subroutine finish_init_g
12✔
3451

3452
  !> Returns the value of [[init_g_knobs:restart_dir]]
3453
  function get_restart_dir()
×
3454
    character(len=:), allocatable :: get_restart_dir
3455
    get_restart_dir = restart_dir
×
3456
  end function get_restart_dir
×
3457

3458
  !> Sets the value of the module level restart_dir
3459
  subroutine set_restart_dir(restart_dir_in)
×
3460
    character(len=*), intent(in) :: restart_dir_in
3461
    restart_dir = restart_dir_in
×
3462
  end subroutine set_restart_dir
×
3463

3464
#include "init_g_auto_gen.inc"
3465
end module init_g
×
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