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

gyrokinetics / gs2 / 1663582644

10 Feb 2025 10:47AM UTC coverage: 7.92% (+0.003%) from 7.917%
1663582644

push

gitlab-ci

David Dickinson
Merged in bugfix/make_sure_multigs2_actually_times_jobs (pull request #1094)

3690 of 46590 relevant lines covered (7.92%)

99873.61 hits per line

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

0.0
/src/hyper.f90
1
!> FIXME : Add documentation
2
!!
3
!! @note nexp has been changed in a rush.  Only known to be correct for nexp=2
4
module hyper
5
  use abstract_config, only: abstract_config_type, CONFIG_MAX_NAME_LEN
6
  implicit none
7

8
  private
9

10
  public :: init_hyper, finish_hyper, hyper_diff, D_res, D_v, D_eta, nexp
11
  public :: read_parameters, wnml_hyper, check_hyper, hypervisc_filter
12

13
  public :: hyper_config_type, set_hyper_config, get_hyper_config
14

15
  ! D_v, D_eta are hyper coefficients, normalized correctly
16
  ! i.e., either by unity or by 1/k_perp**2*nexp
17
  real :: D_v, D_eta, D_hypervisc, D_hyperres, omega_osc, D_hyper
18
  real :: akx4_max, aky4_max, aky_max, akperp4_max
19

20
  integer :: hyper_option_switch, nexp
21
  integer, parameter :: hyper_option_none = 1, &
22
       hyper_option_visc = 2, &
23
       hyper_option_res  = 3, &
24
       hyper_option_both = 4, &
25
       hyper_option_simple3D = 5
26

27
  character(9) :: hyper_option
28
  logical :: const_amp, isotropic_shear, damp_zonal_only, gridnorm
29

30
  real, dimension (:, :), allocatable :: D_res
31
  real, dimension (:, :, :), allocatable :: hypervisc_filter
32

33
  ! Coefficients for simple3D hyperviscous model
34
  ! the maximum k_perp ^ 2 including geometric coefficients for non-zonal and zonal modes
35
  real :: kperp2_max, kperp2_max_zonal
36
  ! Hyperviscous coefficient, hyperviscous power, ky cut-off, kx cut-off
37
  real :: D_hyper3D, P_hyper3D, ky_cut, kx_cut
38
  ! Controls if zonal modes are treated identically to non-zonal modes
39
  logical :: isotropic_model
40
  logical :: initialized = .false., hyper_on = .false.
41

42
  !> Used to represent the input configuration of hyper
43
  type, extends(abstract_config_type) :: hyper_config_type
44
     ! namelist : hyper_knobs
45
     ! indexed : false
46
     !> Determines whether hyperviscosity includes time dependent amplitude
47
     !> factor when calculating damping rate. Recommend `true` for
48
     !> linear runs and `false` for nolinear runs, since amplutide of
49
     !> turbulence grows linearly with time in linear run.
50
     logical :: const_amp = .false.
51
     !> If `hyper_option = 'both'` is used then this sets both the
52
     !> hyperresistivity and hyperviscosity damping coefficients. Can
53
     !> override the individual coefficients with
54
     !> [[hyper_knobs:D_hyperres]] and [[hyper_knobs:D_hypervisc]].
55
     real :: d_hyper = -10.0
56
     !> Used with the simple3D hyperviscosity model of the form
57
     !> D_hyper3D * (|kperp|/ max |kperp|)^P_hyper3D
58
     !> and ky_cut, kx_cut set max |kperp|
59
     real :: d_hyper3d = -10.
60
     !> Sets hyperresistivity parameter multiplying damping term.
61
     real :: d_hyperres = -10.0
62
     !> Sets hyperviscosity parameter multiplying damping term. See
63
     !> [E. Belli (2006)
64
     !> thesis](https://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=50BFD54A8F8D72FC225D025FDEDFFFA5?doi=10.1.1.706.9568&rep=rep1&type=pdf)
65
     !> for more information.
66
     real :: d_hypervisc = -10.0
67
     !> If `true` then hyperdissipation only applied to the zonal
68
     !> mode.
69
     logical :: damp_zonal_only = .false.
70
     !> If `true` (default) then set wavenumber parameters entering
71
     !> the models based on the maximum `ky` and `kx` included in the
72
     !> current simulation. If `false` then these values are set to 1.
73
     logical :: gridnorm = .true.
74
     !> Selects the type of hyper terms included. Should be one of
75
     !>
76
     !> - 'default' -- no hyper terms included.
77
     !> - 'none' -- the same as default.
78
     !> - 'visc_only' -- only hyperviscosity included.
79
     !> - 'res_only' -- only hyperresistivity included.
80
     !> - 'both' -- both viscosity and resistivity included.
81
     !> - 'simple3D' -- simple hyperviscous dissipation rate of the
82
     !>    form D_hyper3D * (|kperp|/ max |kperp|)^P_hyper3D
83
     !>    described in [���Multiscale turbulence in magnetic
84
     !>    confinement fusion devices���, M. Hardman, DPhil Thesis,
85
     !>    appendix
86
     !>    B.4](https://ora.ox.ac.uk/objects/uuid:233a22cb-3c8b-4fe0-a689-4a37d8fe0314)
87
     !>    note that the dissipation in this version is applied to g, not h, as
88
     !>    in the reference.
89
     character(len = 9) :: hyper_option = 'default'
90
     !> if true damp zonal and drift waves with same dissipation formula
91
     logical :: isotropic_model = .true.
92
     !> If `true` then use isotropic shear model.
93
     logical :: isotropic_shear = .true.
94
     !> Used with the simple3D hyperviscosity model of the form
95
     !> D_hyper3D * (|kperp|/ max |kperp|)^P_hyper3D
96
     !> and ky_cut, kx_cut set max |kperp|
97
     real :: kx_cut = -10.
98
     !> Used with the simple3D hyperviscosity model of the form
99
     !> D_hyper3D * (|kperp|/ max |kperp|)^P_hyper3D
100
     !> and ky_cut, kx_cut set max |kperp|
101
     real :: ky_cut = -10.
102
     !> Sets the power to which \(k_\bot^2\) is raised in the dissipation filter.
103
     integer :: nexp = 2
104
     !> Sets a parameter in the anisotropic shearing rate calculation.
105
     real :: omega_osc = 0.4
106
     !> Used with the simple3D hyperviscosity model of the form
107
     !> D_hyper3D * (|kperp|/ max |kperp|)^P_hyper3D
108
     !> and ky_cut, kx_cut set max |kperp|
109
     real :: p_hyper3d = 4.
110
   contains
111
     procedure, public :: read => read_hyper_config
112
     procedure, public :: write => write_hyper_config
113
     procedure, public :: reset => reset_hyper_config
114
     procedure, public :: broadcast => broadcast_hyper_config
115
     procedure, public, nopass :: get_default_name => get_default_name_hyper_config
116
     procedure, public, nopass :: get_default_requires_index => get_default_requires_index_hyper_config
117
  end type hyper_config_type
118

119
  type(hyper_config_type) :: hyper_config
120

121
contains
122

123
  !> FIXME : Add documentation
124
  subroutine check_hyper(report_unit)
×
125
    implicit none
126
    integer, intent(in) :: report_unit
127
    select case (hyper_option_switch)
×
128
    case (hyper_option_none)
129
       if (D_hyperres > 0.) then
×
130
          write (report_unit, *)
×
131
          write (report_unit, fmt="('################# WARNING #######################')")
×
132
          write (report_unit, fmt="('hyper_option = ',a,' chooses no hyperresistivity.  &
133
               &D_hyperres ignored.')") trim(hyper_option)
×
134
          write (report_unit, fmt="('################# WARNING #######################')")
×
135
          write (report_unit, *)
×
136
          D_hyperres = -10.
×
137
       end if
138
       if (D_hypervisc > 0.) then
×
139
          write (report_unit, *)
×
140
          write (report_unit, fmt="('################# WARNING #######################')")
×
141
          write (report_unit, fmt="('hyper_option = ',a,' chooses no hyperviscosity.  &
142
               &D_hypervisc ignored.')") trim(hyper_option)
×
143
          write (report_unit, fmt="('################# WARNING #######################')")
×
144
          write (report_unit, *)
×
145
          D_hypervisc = -10.
×
146
       endif
147

148
    case (hyper_option_visc)
149
       hyper_on = .true.
×
150
       if (D_hyperres > 0.) then
×
151
          write (report_unit, *)
×
152
          write (report_unit, fmt="('################# WARNING #######################')")
×
153
          write (report_unit, fmt="('hyper_option = ',a,' chooses no hyperresistivity.  &
154
               &D_hyperres ignored.')") trim(hyper_option)
×
155
          write (report_unit, fmt="('################# WARNING #######################')")
×
156
          write (report_unit, *)
×
157
          D_hyperres = -10.
×
158
       end if
159
       if (D_hypervisc < 0.) then
×
160
          write (report_unit, *)
×
161
          write (report_unit, fmt="('################# WARNING #######################')")
×
162
          write (report_unit, fmt="('hyper_option = ',a,' chooses hyperviscosity but &
163
               &D_hypervisc < 0.')") trim(hyper_option)
×
164
          write (report_unit, fmt="('No hyperviscosity used.')")
×
165
          write (report_unit, fmt="('################# WARNING #######################')")
×
166
          write (report_unit, *)
×
167
          hyper_on = .false.
×
168
       endif
169

170
    case (hyper_option_res)
171
       hyper_on = .true.
×
172
       if (D_hyperres < 0.) then
×
173
          write (report_unit, *)
×
174
          write (report_unit, fmt="('################# WARNING #######################')")
×
175
          write (report_unit, fmt="('hyper_option = ',a,' chooses hyperresistivity but D_hyperres < 0.')") trim(hyper_option)
×
176
          write(report_unit, fmt="('No hyperresistivity used.')")
×
177
          write (report_unit, fmt="('################# WARNING #######################')")
×
178
          write (report_unit, *)
×
179
          hyper_on = .false.
×
180
       end if
181
       if (D_hypervisc > 0.) then
×
182
          write (report_unit, *)
×
183
          write (report_unit, fmt="('################# WARNING #######################')")
×
184
          write (report_unit, fmt="('hyper_option = ',a,' chooses no hyperviscosity.  D_hypervisc ignored.')") trim(hyper_option)
×
185
          write (report_unit, fmt="('################# WARNING #######################')")
×
186
          write (report_unit, *)
×
187
          D_hypervisc = -10.
×
188
       endif
189

190
    case (hyper_option_both)
191
       hyper_on = .true.
×
192
       if (D_hyperres < 0.) then
×
193
          write (report_unit, *)
×
194
          write (report_unit, fmt="('################# WARNING #######################')")
×
195
          write (report_unit, fmt="('hyper_option = ',a,' chooses hyperresistivity but D_hyperres < 0.')") trim(hyper_option)
×
196
          write (report_unit, fmt="('No hyperresistivity used.')")
×
197
          write (report_unit, fmt="('################# WARNING #######################')")
×
198
          write (report_unit, *)
×
199
       end if
200
       if (D_hypervisc < 0.) then
×
201
          write (report_unit, *)
×
202
          write (report_unit, fmt="('################# WARNING #######################')")
×
203
          write (report_unit, fmt="('hyper_option = ',a,' chooses hyperviscosity but D_hypervisc < 0.')") trim(hyper_option)
×
204
          write (report_unit, fmt="('No hyperviscosity used.')")
×
205
          write (report_unit, fmt="('################# WARNING #######################')")
×
206
          write (report_unit, *)
×
207
       endif
208
       if (D_hypervisc < 0. .and. D_hyperres < 0.) hyper_on = .false.
×
209

210
    end select
211

212
    if (hyper_on) then
×
213
       write (report_unit, *)
×
214
       write (report_unit, fmt="('------------------------------------------------------------')")
×
215
       write (report_unit, *)
×
216

217
       select case (hyper_option_switch)
×
218

219
       case (hyper_option_visc)
220

221
          write (report_unit, *)
×
222
          write (report_unit, fmt="('Hyperviscosity included without hyperresistivity.')")
×
223
          if (const_amp) then
×
224
             write (report_unit, fmt="('Damping rate is ',e11.4,' at highest k_perp.')") D_hypervisc
×
225
          else
226
             write (report_unit, fmt="('The damping coefficent is ',e11.4)") D_hypervisc
×
227
             write (report_unit, fmt="('The damping rate is proportional to the RMS amplitude of the turbulence.')")
×
228
          end if
229
          if (isotropic_shear) then
×
230
             write (report_unit, fmt="('The hyperviscosity is isotropic in the perpendicular plane.')")
×
231
             write (report_unit, fmt="('This is appropriate for MHD-like calculations.')")
×
232
          else
233
             write (report_unit, fmt="('The hyperviscosity is anisotropic in the perpendicular plane.')")
×
234
             write (report_unit, fmt="('This is appropriate for drift-type calculations.')")
×
235
             write (report_unit, fmt="('omega_osc = ',e11.4)") omega_osc
×
236
          end if
237

238
       case (hyper_option_res)
239

240
          write (report_unit, *)
×
241
          write (report_unit, fmt="('Hyperresistivity included without hyperviscosity.')")
×
242
          if (const_amp) then
×
243
             write (report_unit, fmt="('Damping rate is ',e11.4,' at highest k_perp.')") D_hyperres
×
244
          else
245
             write (report_unit, fmt="('################# WARNING #######################')")
×
246
             write (report_unit, fmt="('const_amp = .false. is not implemented for hyperresistivity.')")
×
247
             write (report_unit, fmt="('################# WARNING #######################')")
×
248
             write (report_unit, *)
×
249
          end if
250
          if (isotropic_shear) then
×
251
             write (report_unit, fmt="('The hyperresistivity is isotropic in the perpendicular plane.')")
×
252
             write (report_unit, fmt="('This is appropriate for MHD-like calculations.')")
×
253
          else
254
             write (report_unit, fmt="('################# WARNING #######################')")
×
255
             write (report_unit, fmt="('isotropic_shear = .false. is not implemented for hyperresistivity.')")
×
256
             write (report_unit, fmt="('################# WARNING #######################')")
×
257
             write (report_unit, *)
×
258
          end if
259

260
       case (hyper_option_both)
261

262
          write (report_unit, *)
×
263
          write (report_unit, fmt="('Hyperresistivity and hyperviscosity included.')")
×
264
          if (const_amp) then
×
265
             write (report_unit, fmt="('Damping rate is ',e11.4,' at highest k_perp.')") D_hyperres
×
266
          else
267
             write (report_unit, fmt="('################# WARNING #######################')")
×
268
             write (report_unit, fmt="('const_amp = .false. is not implemented for hyperresistivity.')")
×
269
             write (report_unit, fmt="('THIS IS AN ERROR.')")
×
270
             write (report_unit, fmt="('################# WARNING #######################')")
×
271
             write (report_unit, *)
×
272
          end if
273
          if (isotropic_shear) then
×
274
             write (report_unit, fmt="('The damping is isotropic in the perpendicular plane.')")
×
275
             write (report_unit, fmt="('This is appropriate for MHD-like calculations.')")
×
276
          else
277
             write (report_unit, fmt="('################# WARNING #######################')")
×
278
             write (report_unit, fmt="('isotropic_shear = .false. is not implemented for hyperresistivity.')")
×
279
             write (report_unit, fmt="('THIS IS AN ERROR.')")
×
280
             write (report_unit, fmt="('################# WARNING #######################')")
×
281
             write (report_unit, *)
×
282
          end if
283
       end select
284
    end if
285
  end subroutine check_hyper
×
286

287
  !> FIXME : Add documentation
288
  subroutine wnml_hyper(unit)
×
289
    implicit none
290
    integer, intent(in) :: unit
291
    if (.not. hyper_on) return
×
292
    write (unit, *)
×
293
    write (unit, fmt="(' &',a)") "hyper_knobs"
×
294

295
    select case (hyper_option_switch)
×
296

297
    case (hyper_option_visc)
298
       write (unit, fmt="(' hyper_option = ',a)") '"visc_only"'
×
299
       write (unit, fmt="(' D_hypervisc = ',e17.10)") D_hypervisc
×
300

301
    case (hyper_option_res)
302
       write (unit, fmt="(' hyper_option = ',a)") '"res_only"'
×
303
       write (unit, fmt="(' D_hyperres = ',e17.10)") D_hyperres
×
304

305
    case (hyper_option_both)
306
       write (unit, fmt="(' hyper_option = ',a)") '"both"'
×
307
       if (D_hyperres == D_hypervisc) then
×
308
          write (unit, fmt="(' D_hyper = ',e17.10)") D_hyper
×
309
       else
310
          write (unit, fmt="(' D_hypervisc = ',e17.10)") D_hypervisc
×
311
          write (unit, fmt="(' D_hyperres = ',e17.10)") D_hyperres
×
312
       end if
313
    end select
314

315
    select case (hyper_option_switch)
×
316

317
    case (hyper_option_visc, hyper_option_res, hyper_option_both)
318
!    write (unit, fmt="(' include_kpar = ',L1)") include_kpar
319

320
    write (unit, fmt="(' const_amp = ',L1)") const_amp
×
321
    write (unit, fmt="(' isotropic_shear = ',L1)") isotropic_shear
×
322
    if (.not. isotropic_shear) &
×
323
         write (unit, fmt="(' omega_osc = ',e17.10)") omega_osc
×
324

325
    write (unit, fmt="(' gridnorm = ',L1)") gridnorm
×
326
    write (unit, fmt="(' /')")
×
327

328
    case (hyper_option_simple3D)
329
    write (unit, fmt="(' hyper_option = ',a)") '"simple3D"'
×
330
    write (unit, fmt="(' D_hyper3D = ',e17.10)") D_hyper3D
×
331
    write (unit, fmt="(' P_hyper3D = ',e17.10)") P_hyper3D
×
332
    if (ky_cut > 0.) &
×
333
         write (unit, fmt="(' ky_cut = ',e17.10)") ky_cut
×
334
    if (kx_cut > 0.) &
×
335
         write (unit, fmt="(' kx_cut = ',e17.10)") kx_cut
×
336
    write (unit, fmt="(' isotropic_model = ',L1)") isotropic_model
×
337
    write (unit, fmt="(' /')")
×
338

339
    end select
340
  end subroutine wnml_hyper
341

342
  !> FIXME : Add documentation
343
  subroutine init_hyper(hyper_config_in)
×
344
    use kt_grids, only: ntheta0, naky, akx, aky, kperp2
345
    use theta_grid, only: gds2, gds21, gds22, shat
346
    use gs2_time, only: code_dt
347
    use gs2_layouts, only: init_gs2_layouts
348
    implicit none
349
    type(hyper_config_type), intent(in), optional :: hyper_config_in
350
    integer :: ik, it
351

352
    if (initialized) return
×
353
    initialized = .true.
×
354

355
    call init_gs2_layouts
×
356
    call read_parameters(hyper_config_in)
×
357
    call allocate_arrays
×
358

359
    select case (hyper_option_switch)
×
360
    case(hyper_option_both, hyper_option_res, hyper_option_visc)
361
       ! Define variables used in hyperviscosity and hyperresistivity models
362
       if (gridnorm) then
×
363
          akx4_max = akx(ntheta0 / 2 + 1)**(2 * nexp)
×
364
          aky_max = aky(naky)
×
365
          aky4_max = aky(naky)**(2 * nexp)
×
366
          akperp4_max = (akx(ntheta0 / 2 + 1)**2  +  aky(naky)**2)**nexp
×
367
       else
368
          akx4_max = 1.
×
369
          aky_max = 1.
×
370
          aky4_max = 1.
×
371
          akperp4_max = 1.
×
372
       end if
373

374
       ! Get D_res set up if needed
375
       if (D_hyperres > 0.) then
×
376
          do ik = 1, naky
×
377
             do it = 1, ntheta0
×
378
                D_res(it, ik) = D_hyperres*code_dt * (aky(ik)**2 + akx(it)**2)**nexp &
×
379
                     / akperp4_max
×
380
             end do
381
          end do
382
          D_eta = D_hyperres / akperp4_max
×
383
       end if
384

385
       if (D_hypervisc > 0.) D_v = D_hypervisc / akperp4_max
×
386

387
    case(hyper_option_simple3D)
388
       ! Make the default cut-offs the grid scale
389
       if (ky_cut <= 0.) ky_cut = aky(naky)
×
390
       if (kx_cut <= 0.) kx_cut = akx((ntheta0+1)/2)
×
391

392
       ! Here we're evaluating kperp2 for the specified ky, kx value
393
       kperp2_max = maxval(ky_cut * ky_cut * gds2 + &
×
394
            2.0 * ky_cut * kx_cut * gds21 / shat + &
×
395
            kx_cut * kx_cut * gds22 / (shat * shat))
×
396

397
       if (isotropic_model) then
×
398
          kperp2_max_zonal = kperp2_max
×
399
       else
400
          kperp2_max_zonal = maxval(kx_cut * kx_cut * gds22 / (shat * shat))
×
401
       end if
402

403
       ! Calculate the filter
404
       ik =1  ! Zonal modes
×
405
       do it = 1, ntheta0
×
406
          hypervisc_filter(:, it, ik) = exp(- ( D_hyper3D * code_dt &
×
407
               * ( kperp2(:, it, ik) / kperp2_max_zonal)**(P_hyper3D / 2)))
×
408
       end do
409

410
       do ik = 2, naky ! Non-zonal modes
×
411
          do it = 1, ntheta0
×
412
             hypervisc_filter(:, it, ik) = exp(- ( D_hyper3D * code_dt &
×
413
                  * ( kperp2(:, it, ik) / kperp2_max )**(P_hyper3D / 2)) )
×
414
          end do
415
       end do
416
    end select
417
  end subroutine init_hyper
418

419
  !> FIXME : Add documentation
420
  subroutine read_parameters(hyper_config_in)
×
421
    use file_utils, only: error_unit
422
    use text_options, only: text_option, get_option_value
423
    use mp, only: proc0
424
    implicit none
425
    type(hyper_config_type), intent(in), optional :: hyper_config_in
426
    type (text_option), dimension(6), parameter :: hyperopts = &
427
         (/ text_option('default', hyper_option_none), &
428
            text_option('none', hyper_option_none), &
429
            text_option('visc_only', hyper_option_visc), &
430
            text_option('res_only', hyper_option_res), &
431
            text_option('both', hyper_option_both), &
432
            text_option('simple3D', hyper_option_simple3D) /)
433
    integer :: ierr
434

435
    if (present(hyper_config_in)) hyper_config = hyper_config_in
×
436

437
    call hyper_config%init(name = 'hyper_knobs', requires_index = .false.)
×
438

439
    ! Copy out internal values into module level parameters
440
    associate(self => hyper_config)
441
#include "hyper_copy_out_auto_gen.inc"
442
    end associate
443

444
    ierr = error_unit()
×
445

446
    call get_option_value &
447
         (hyper_option, hyperopts, hyper_option_switch, &
448
         ierr, "hyper_option in hyper_knobs",.true.)
×
449

450
    if (.not. isotropic_shear .and. nexp /= 2) then
×
451
       if (proc0) write (ierr, *) 'Forcing nexp = 2.  Higher values not implemented for anisotropic shear model.'
×
452
       nexp = 2
×
453
    end if
454

455

456
    select case (hyper_option_switch)
×
457
    case (hyper_option_none)
458
       if (D_hyperres > 0.) then
×
459
          if (proc0) write(ierr, *) 'hyper_option = ',hyper_option, &
×
460
               ' chooses no hyperresistivity.  D_hyperres ignored.'
×
461
          D_hyperres = -10.
×
462
       end if
463
       if (D_hypervisc > 0.) then
×
464
          if (proc0) write(ierr, *) 'hyper_option = ',hyper_option, &
×
465
               ' chooses no hyperviscosity.  D_hypervisc ignored.'
×
466
          D_hypervisc = -10.
×
467
       endif
468

469
    case (hyper_option_visc)
470
       hyper_on = .true.
×
471
       if (proc0) write (ierr, *) 'WARNING: It is inconsistent to set D_hypervisc different from ', &
×
472
            'D_hyperres.  Recommend: Set them equal.'
×
473
       if (D_hyperres > 0.) then
×
474
          if (proc0) write(ierr, *) 'hyper_option = ',hyper_option, &
×
475
               ' chooses no hyperresistivity.  D_hyperres ignored.'
×
476
          D_hyperres = -10.
×
477
       end if
478
       if (D_hypervisc < 0.) then
×
479
          if (proc0) then
×
480
             write(ierr, *) 'hyper_option = ',hyper_option, &
×
481
                  ' chooses hyperviscosity but D_hypervisc < 0 is illegal.'
×
482
             write(ierr, *) 'No hyperviscosity used.'
×
483
          end if
484
          hyper_on = .false.
×
485
       endif
486

487
    case (hyper_option_res)
488
       hyper_on = .true.
×
489
       if (proc0) write (ierr, *) 'WARNING: It is inconsistent to set D_hypervisc different from ', &
×
490
            'D_hyperres.  Recommend: Set them equal.'
×
491
       if (D_hyperres < 0.) then
×
492
          if (proc0) then
×
493
             write(ierr, *) 'hyper_option = ',hyper_option, &
×
494
                  ' chooses hyperresistivity but  D_hyperres < 0 is illegal.'
×
495
             write(ierr, *) 'No hyperresistivity used.'
×
496
          end if
497
          hyper_on = .false.
×
498
       end if
499
       if (D_hypervisc > 0.) then
×
500
          if (proc0) write(ierr, *) 'hyper_option = ',hyper_option, &
×
501
               ' chooses no hyperviscosity.  D_hypervisc ignored.'
×
502
          D_hypervisc = -10.
×
503
       endif
504

505
    case (hyper_option_both)
506
       hyper_on = .true.
×
507

508
       if (D_hyper < 0.) then
×
509
          if (D_hyperres /= D_hyperres) then
×
510
             if (proc0) write (ierr, *) 'WARNING: It is inconsistent to set D_hypervisc different from ', &
×
511
                  'D_hyperres.  Recommend: Set them equal.'
×
512
          end if
513
       else
514
          if (proc0) write (ierr, *) 'WARNING: Setting D_hypervisc = D_hyperres, each to value of D_hyper'
×
515
          D_hyperres  = D_hyper
×
516
          D_hypervisc = D_hyper
×
517
       end if
518

519
       if (D_hyperres < 0.) then
×
520
          if (proc0) then
×
521
             write(ierr, *) 'hyper_option = ',hyper_option, &
×
522
                  ' chooses hyperresistivity but  D_hyperres < 0 is illegal.'
×
523
             write(ierr, *) 'No hyperresistivity used.'
×
524
          end if
525
       end if
526
       if (D_hypervisc < 0.) then
×
527
          if (proc0) then
×
528
             write(ierr, *) 'hyper_option = ',hyper_option, &
×
529
                  ' chooses hyperviscosity but D_hypervisc < 0 is illegal.'
×
530
             write(ierr, *) 'No hyperviscosity used.'
×
531
          end if
532
       endif
533
       if (D_hypervisc < 0. .and. D_hyperres < 0.) hyper_on = .false.
×
534

535
    case (hyper_option_simple3D) ! MRH
536
       hyper_on = .true.
×
537

538
       if (P_hyper3D < 4.) then
×
539
          hyper_on = .false.
×
540
          if(proc0) write(ierr, *) 'hyper_option = ',hyper_option, &
×
541
               ' chooses a simple hyperviscous filter but  P_hyper3D < 4. is illegal.'
×
542
          if(proc0) write(ierr, *) 'No hyperviscosity used.'
×
543
       endif
544

545
       if (D_hyper3D < 0.) then
×
546
          hyper_on = .false.
×
547
          if(proc0) write(ierr, *) 'hyper_option = ',hyper_option, &
×
548
               ' chooses a simple hyperviscous filter but  D_hyper3D < 0 is illegal.'
×
549
          if(proc0) write(ierr, *) 'No hyperviscosity used.'
×
550
       endif
551
    end select
552
  end subroutine read_parameters
×
553

554
  !> FIXME : Add documentation
555
  subroutine allocate_arrays
×
556
    use theta_grid, only: ntgrid
557
    use kt_grids, only: ntheta0, naky
558
    implicit none
559

560
    if (.not. allocated(D_res)) allocate(D_res(ntheta0, naky))
×
561
    if (.not. allocated(hypervisc_filter)) &
×
562
         allocate(hypervisc_filter(-ntgrid:ntgrid,ntheta0,naky))
×
563

564
    ! Initialise module level variables
565
    D_v = 0 ;  D_eta = 0 ; D_res = 0
×
566
    akx4_max = 0 ; aky_max = 0 ; aky4_max = 0 ; akperp4_max = 0
×
567
    kperp2_max = 0 ; kperp2_max_zonal = 0 ; hypervisc_filter = 1
×
568
  end subroutine allocate_arrays
×
569

570
  !> FIXME : Add documentation
571
  subroutine hyper_diff (g0, phi)
×
572
    use gs2_layouts, only: g_lo, ik_idx, it_idx, is_idx
573
    use theta_grid, only: ntgrid
574
    use gs2_time, only: code_dt
575
    use kt_grids, only: aky, akx, naky, ntheta0
576
    implicit none
577
    complex, dimension (-ntgrid:,:,g_lo%llim_proc:), intent (in out) :: g0
578
    complex, dimension (-ntgrid:,:,:), intent (in) :: phi
579
    real, dimension (-ntgrid:ntgrid) :: shear_rate_nz, shear_rate_z, shear_rate_z_nz
×
580
    integer :: iglo, ik, it
581

582
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
583
!
584
! Includes models by Belli and Hammett
585
! to calculate the x-y avged shearing rate
586
! S(theta)^2 = <|grad_perp|^4 |phi|^2>
587
!            =  sum_over_k(kperp^4 * |phi|^2)
588
!               (times crazy fac factor due to FFT conventions.)
589
!
590
! and to implement this anisotropically in k_perp, taking into
591
! account properties of zonal flows.
592
!
593
! Begun December 2001
594
!
595
! Number conservation added April 2006
596
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
597

598
    if (.not. hyper_on) return
×
599

600
    ! Calculate hypervisc filter for non-simple3D model
601
    select case (hyper_option_switch)
×
602
    case(hyper_option_both, hyper_option_res, hyper_option_visc)
603
       if (D_hypervisc < 0.) return
×
604

605
       if(isotropic_shear) then
×
606
          call iso_shear
×
607
       else
608
          call aniso_shear
×
609
       end if
610
    end select
611

612
    ! Apply hypervisc filter
613
    !$OMP PARALLEL DO DEFAULT(none) &
614
    !$OMP PRIVATE(iglo, ik, it) &
615
    !$OMP SHARED(g_lo, damp_zonal_only, g0, hypervisc_filter) &
616
    !$OMP SCHEDULE(static)
617
    do iglo = g_lo%llim_proc, g_lo%ulim_alloc
×
618
       ik = ik_idx(g_lo, iglo)
×
619
       it = it_idx(g_lo, iglo)
×
620
       if (damp_zonal_only .and. ik /= 1) cycle
×
621
       g0(:, 1, iglo) = g0(:, 1, iglo) * hypervisc_filter(:, it, ik)
×
622
       g0(:, 2, iglo) = g0(:, 2, iglo) * hypervisc_filter(:, it, ik)
×
623
    end do
624
    !$OMP END PARALLEL DO
625
  contains
626

627
    !> FIXME : Add documentation
628
    subroutine aniso_shear
×
629
      real, dimension(naky) :: fac
×
630
      ! Do the Belli-Hammett anisotropic calculation
631
      ! which accounts for some zonal/non-zonal differences
632
      fac = 0.5
×
633
      fac(1) = 1.0
×
634

635
      ! shearing rate due to non-zonal modes (on nonzonal modes)
636
      shear_rate_nz = 0.
×
637
      ! shearing rate due to zonal modes (on nonzonal modes)
638
      shear_rate_z = 0
×
639
      ! shearing rate due to nonzonal modes (on zonal modes)
640
      shear_rate_z_nz = 0.
×
641

642
      ik = 1
×
643
      !$OMP PARALLEL DO DEFAULT(none) &
644
      !$OMP PRIVATE(it) &
645
      !$OMP SHARED(ik, ntheta0, phi, akx, aky, fac) &
646
      !$OMP REDUCTION(+: shear_rate_z) &
647
      !$OMP SCHEDULE(static)
648
      do it = 1, ntheta0
×
649
         shear_rate_z = shear_rate_z + real(conjg(phi(:, it, ik)) &
×
650
              * phi(:, it, ik)) * (akx(it)**2 + aky(ik)**2)**2 * fac(ik)
×
651
      end do
652
      !$OMP END PARALLEL DO
653

654
      !$OMP PARALLEL DO DEFAULT(none) &
655
      !$OMP PRIVATE(ik, it) &
656
      !$OMP SHARED(naky, ntheta0, phi, akx, aky, fac) &
657
      !$OMP REDUCTION(+: shear_rate_nz, shear_rate_z_nz) &
658
      !$OMP SCHEDULE(static)
659
      do ik = 2, naky
×
660
         do it = 1, ntheta0
×
661
            shear_rate_nz = shear_rate_nz + real(conjg(phi(:, it, ik)) &
×
662
                 * phi(:, it, ik)) * (akx(it)**2 + aky(ik)**2)**2 * fac(ik)
×
663
            shear_rate_z_nz = shear_rate_z_nz + real(conjg(phi(:, it, ik)) &
×
664
                 * phi(:, it, ik)) * aky(ik)**4 * fac(ik)
×
665
         end do
666
      end do
667
      !$OMP END PARALLEL DO
668

669
      ! shear_rate = shear_rate ** 0.5
670
      shear_rate_nz = 0.5 * ( -omega_osc + sqrt(omega_osc ** 2 + 2 * shear_rate_nz))
×
671
      shear_rate_z_nz = 0.5 * ( -omega_osc + sqrt(omega_osc ** 2 + 2 * shear_rate_z_nz))
×
672
      shear_rate_z = 0.5 * ( -omega_osc + sqrt(omega_osc ** 2 + 2 * shear_rate_z))
×
673
      ! end of anisotropic shearing rate calculations
674

675
      ik = 1
×
676
      !$OMP PARALLEL DO DEFAULT(none) &
677
      !$OMP PRIVATE(it) &
678
      !$OMP SHARED(ik, ntheta0, hypervisc_filter, D_hypervisc, code_dt, akx, &
679
      !$OMP shear_rate_z_nz, akx4_max) &
680
      !$OMP SCHEDULE(static)
681
      do it = 1, ntheta0
×
682
         hypervisc_filter(:, it, ik) = exp(- (D_hypervisc * code_dt &
×
683
              * (shear_rate_z_nz * akx(it) ** 4 / akx4_max )))
×
684
      end do
685
      !$OMP END PARALLEL DO
686

687
      !$OMP PARALLEL DO DEFAULT(none) &
688
      !$OMP PRIVATE(ik, it) &
689
      !$OMP SHARED(naky, ntheta0, hypervisc_filter, D_hypervisc, code_dt, akx, aky, &
690
      !$OMP shear_rate_nz, shear_rate_z, nexp, akperp4_max, akx4_max, aky_max) &
691
      !$OMP SCHEDULE(static)
692
      do ik = 2, naky
×
693
         do it = 1, ntheta0
×
694
            hypervisc_filter(:, it, ik) = exp(- ( D_hypervisc * code_dt &
×
695
                 * ( shear_rate_nz *  (aky(ik) ** 2 + akx(it) ** 2 )**nexp / akperp4_max &
×
696
                 + shear_rate_z * (akx(it) ** 4) * aky(ik) / (akx4_max * aky_max))))
×
697
         end do
698
      end do
699
      !$OMP END PARALLEL DO
700
    end subroutine aniso_shear
×
701

702
    !> FIXME : Add documentation
703
    subroutine iso_shear
×
704
      real, dimension(naky) :: fac
×
705
      if (const_amp) then
×
706
         shear_rate_nz = 1.
×
707
      else
708
         fac = 0.5
×
709
         fac(1) = 1.0
×
710
         shear_rate_nz = 0.
×
711
         do ik = 1, naky
×
712
            if (damp_zonal_only .and. ik > 1) exit
×
713
            do it = 1, ntheta0
×
714
               shear_rate_nz = shear_rate_nz &
×
715
                    + real(conjg(phi(:, it, ik)) * phi(:, it, ik)) &
×
716
                    * (akx(it)**2 + aky(ik)**2)**2 * fac(ik)
×
717
            end do
718
         end do
719
         shear_rate_nz = sqrt(shear_rate_nz)
×
720
      end if
721

722
      do ik = 1, naky
×
723
         !Rely on hypervisc_filter initialised to 1
724
         if (damp_zonal_only .and. ik > 1) exit
×
725
         do it = 1, ntheta0
×
726
            hypervisc_filter(:, it, ik) = exp(- ( D_hypervisc * code_dt &
×
727
                 * ( shear_rate_nz *  (aky(ik) ** 2 + akx(it) ** 2 )**nexp / akperp4_max)))
×
728
         end do
729
      end do
730
    end subroutine iso_shear
×
731
  end subroutine hyper_diff
732

733
  !> FIXME : Add documentation
734
  subroutine finish_hyper
×
735
    implicit none
736
    hyper_on = .false.
×
737
    initialized = .false.
×
738
    if (allocated(D_res)) deallocate(D_res)
×
739
    if (allocated(hypervisc_filter)) deallocate(hypervisc_filter)
×
740
    call hyper_config%reset()
×
741
  end subroutine finish_hyper
×
742

743
#include "hyper_auto_gen.inc"
744
end module hyper
×
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