forked from openmc-dev/openmc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathglobal.F90
573 lines (448 loc) · 20.2 KB
/
global.F90
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
module global
use bank_header, only: Bank
use cmfd_header
use constants
use dict_header, only: DictCharInt, DictIntInt
use geometry_header, only: Cell, Universe, Lattice, LatticeContainer
use material_header, only: Material
use mesh_header, only: RegularMesh
use mgxs_header, only: Mgxs, MgxsContainer
use nuclide_header
use plot_header, only: ObjectPlot
use sab_header, only: SAlphaBeta
use set_header, only: SetInt
use surface_header, only: SurfaceContainer
use source_header, only: SourceDistribution
use tally_header, only: TallyObject, TallyResult
use trigger_header, only: KTrigger
use timer_header, only: Timer
use volume_header, only: VolumeCalculation
#ifdef MPIF08
use mpi_f08
#endif
implicit none
! ============================================================================
! GEOMETRY-RELATED VARIABLES
! Main arrays
type(Cell), allocatable, target :: cells(:)
type(Universe), allocatable, target :: universes(:)
type(LatticeContainer), allocatable, target :: lattices(:)
type(SurfaceContainer), allocatable, target :: surfaces(:)
type(Material), allocatable, target :: materials(:)
type(ObjectPlot), allocatable, target :: plots(:)
type(VolumeCalculation), allocatable :: volume_calcs(:)
! Size of main arrays
integer :: n_cells ! # of cells
integer :: n_universes ! # of universes
integer :: n_lattices ! # of lattices
integer :: n_surfaces ! # of surfaces
integer :: n_materials ! # of materials
integer :: n_plots ! # of plots
! These dictionaries provide a fast lookup mechanism -- the key is the
! user-specified identifier and the value is the index in the corresponding
! array
type(DictIntInt) :: cell_dict
type(DictIntInt) :: universe_dict
type(DictIntInt) :: lattice_dict
type(DictIntInt) :: surface_dict
type(DictIntInt) :: material_dict
type(DictIntInt) :: mesh_dict
type(DictIntInt) :: tally_dict
type(DictIntInt) :: plot_dict
! Number of lost particles
integer :: n_lost_particles
! ============================================================================
! ENERGY TREATMENT RELATED VARIABLES
logical :: run_CE = .true. ! Run in CE mode?
! ============================================================================
! CROSS SECTION RELATED VARIABLES NEEDED REGARDLESS OF CE OR MG
integer :: n_nuclides_total ! Number of nuclide cross section tables
! Cross section caches
type(NuclideMicroXS), allocatable :: micro_xs(:) ! Cache for each nuclide
type(MaterialMacroXS) :: material_xs ! Cache for current material
! Dictionaries to look up cross sections and listings
type(DictCharInt) :: nuclide_dict
! ============================================================================
! CONTINUOUS-ENERGY CROSS SECTION RELATED VARIABLES
! Cross section arrays
type(Nuclide), allocatable, target :: nuclides(:) ! Nuclide cross-sections
type(SAlphaBeta), allocatable, target :: sab_tables(:) ! S(a,b) tables
integer :: n_sab_tables ! Number of S(a,b) thermal scattering tables
! Minimum/maximum energies
real(8) :: energy_min_neutron = ZERO
real(8) :: energy_max_neutron = INFINITY
! Dictionaries to look up cross sections and listings
type(DictCharInt) :: sab_dict
! Unreoslved resonance probablity tables
logical :: urr_ptables_on = .true.
! What to assume for expanding natural elements
integer :: default_expand = ENDF_BVII1
! Default temperature and method for choosing temperatures
integer :: temperature_method = TEMPERATURE_NEAREST
real(8) :: temperature_tolerance = 10.0_8
real(8) :: temperature_default = 293.6_8
! ============================================================================
! MULTI-GROUP CROSS SECTION RELATED VARIABLES
! Cross section arrays
type(MgxsContainer), allocatable, target :: nuclides_MG(:)
! Cross section caches
type(MgxsContainer), target, allocatable :: macro_xs(:)
! Number of energy groups
integer :: energy_groups
! Energy group structure
real(8), allocatable :: energy_bins(:)
! Midpoint of the energy group structure
real(8), allocatable :: energy_bin_avg(:)
! Inverse velocities of the energy groups (provided or estimated)
real(8), allocatable :: inverse_velocities(:)
! Maximum Data Order
integer :: max_order
! ============================================================================
! TALLY-RELATED VARIABLES
type(RegularMesh), allocatable, target :: meshes(:)
type(TallyObject), allocatable, target :: tallies(:)
integer, allocatable :: matching_bins(:)
real(8), allocatable :: filter_weights(:)
! Pointers for different tallies
type(TallyObject), pointer :: user_tallies(:) => null()
type(TallyObject), pointer :: cmfd_tallies(:) => null()
! Starting index (minus 1) in tallies for each tally group
integer :: i_user_tallies = -1
integer :: i_cmfd_tallies = -1
! Active tally lists
type(SetInt) :: active_analog_tallies
type(SetInt) :: active_tracklength_tallies
type(SetInt) :: active_current_tallies
type(SetInt) :: active_collision_tallies
type(SetInt) :: active_tallies
!$omp threadprivate(active_analog_tallies, active_tracklength_tallies, &
!$omp& active_current_tallies, active_collision_tallies, &
!$omp& active_tallies)
! Global tallies
! 1) collision estimate of k-eff
! 2) absorption estimate of k-eff
! 3) track-length estimate of k-eff
! 4) leakage fraction
type(TallyResult), allocatable, target :: global_tallies(:)
! It is possible to protect accumulate operations on global tallies by using
! an atomic update. However, when multiple threads accumulate to the same
! global tally, it can cause a higher cache miss rate due to
! invalidation. Thus, we use threadprivate variables to accumulate global
! tallies and then reduce at the end of a generation.
real(8) :: global_tally_collision = ZERO
real(8) :: global_tally_absorption = ZERO
real(8) :: global_tally_tracklength = ZERO
real(8) :: global_tally_leakage = ZERO
!$omp threadprivate(global_tally_collision, global_tally_absorption, &
!$omp& global_tally_tracklength, global_tally_leakage)
integer :: n_meshes = 0 ! # of structured meshes
integer :: n_user_meshes = 0 ! # of structured user meshes
integer :: n_tallies = 0 ! # of tallies
integer :: n_user_tallies = 0 ! # of user tallies
! Normalization for statistics
integer :: n_realizations = 0 ! # of independent realizations
real(8) :: total_weight ! total starting particle weight in realization
! Flag for turning tallies on
logical :: tallies_on = .false.
logical :: active_batches = .false.
! Assume all tallies are spatially distinct
logical :: assume_separate = .false.
! Use confidence intervals for results instead of standard deviations
logical :: confidence_intervals = .false.
! ============================================================================
! EIGENVALUE SIMULATION VARIABLES
integer(8) :: n_particles = 0 ! # of particles per generation
integer :: n_batches ! # of batches
integer :: n_inactive ! # of inactive batches
integer :: n_active ! # of active batches
integer :: gen_per_batch = 1 ! # of generations per batch
integer :: current_batch = 0 ! current batch
integer :: current_gen = 0 ! current generation within a batch
integer :: overall_gen = 0 ! overall generation in the run
! ============================================================================
! TALLY PRECISION TRIGGER VARIABLES
integer :: n_max_batches ! max # of batches
integer :: n_batch_interval = 1 ! batch interval for triggers
logical :: pred_batches = .false. ! predict batches for triggers
logical :: trigger_on = .false. ! flag for turning triggers on/off
type(KTrigger) :: keff_trigger ! trigger for k-effective
logical :: satisfy_triggers = .false. ! whether triggers are satisfied
! External source
type(SourceDistribution), allocatable :: external_source(:)
! Source and fission bank
type(Bank), allocatable, target :: source_bank(:)
type(Bank), allocatable, target :: fission_bank(:)
#ifdef _OPENMP
type(Bank), allocatable, target :: master_fission_bank(:)
#endif
integer(8) :: n_bank ! # of sites in fission bank
integer(8) :: work ! number of particles per processor
integer(8), allocatable :: work_index(:) ! starting index in source bank for each process
integer(8) :: current_work ! index in source bank of current history simulated
! Temporary k-effective values
real(8), allocatable :: k_generation(:) ! single-generation estimates of k
real(8) :: keff = ONE ! average k over active batches
real(8) :: keff_std ! standard deviation of average k
real(8) :: k_col_abs = ZERO ! sum over batches of k_collision * k_absorption
real(8) :: k_col_tra = ZERO ! sum over batches of k_collision * k_tracklength
real(8) :: k_abs_tra = ZERO ! sum over batches of k_absorption * k_tracklength
real(8) :: k_combined(2) ! combined best estimate of k-effective
! Shannon entropy
logical :: entropy_on = .false.
real(8), allocatable :: entropy(:) ! shannon entropy at each generation
real(8), allocatable :: entropy_p(:,:,:,:) ! % of source sites in each cell
type(RegularMesh), pointer :: entropy_mesh
! Uniform fission source weighting
logical :: ufs = .false.
type(RegularMesh), pointer :: ufs_mesh => null()
real(8), allocatable :: source_frac(:,:,:,:)
! Write source at end of simulation
logical :: source_separate = .false.
logical :: source_write = .true.
logical :: source_latest = .false.
! ============================================================================
! PARALLEL PROCESSING VARIABLES
! The defaults set here for the number of processors, rank, and master and
! mpi_enabled flag are for when MPI is not being used at all, i.e. a serial
! run. In this case, these variables are still used at times.
integer :: n_procs = 1 ! number of processes
integer :: rank = 0 ! rank of process
logical :: master = .true. ! master process?
logical :: mpi_enabled = .false. ! is MPI in use and initialized?
integer :: mpi_err ! MPI error code
#ifdef MPIF08
type(MPI_Datatype) :: MPI_BANK
type(MPI_Datatype) :: MPI_TALLYRESULT
#else
integer :: MPI_BANK ! MPI datatype for fission bank
integer :: MPI_TALLYRESULT ! MPI datatype for TallyResult
#endif
#ifdef _OPENMP
integer :: n_threads = NONE ! number of OpenMP threads
integer :: thread_id ! ID of a given thread
#endif
! No reduction at end of batch
logical :: reduce_tallies = .true.
! ============================================================================
! TIMING VARIABLES
type(Timer) :: time_total ! timer for total run
type(Timer) :: time_initialize ! timer for initialization
type(Timer) :: time_read_xs ! timer for reading cross sections
type(Timer) :: time_unionize ! timer for material xs-energy grid union
type(Timer) :: time_bank ! timer for fission bank synchronization
type(Timer) :: time_bank_sample ! timer for fission bank sampling
type(Timer) :: time_bank_sendrecv ! timer for fission bank SEND/RECV
type(Timer) :: time_tallies ! timer for accumulate tallies
type(Timer) :: time_inactive ! timer for inactive batches
type(Timer) :: time_active ! timer for active batches
type(Timer) :: time_transport ! timer for transport only
type(Timer) :: time_finalize ! timer for finalization
! ===========================================================================
! VARIANCE REDUCTION VARIABLES
logical :: survival_biasing = .false.
real(8) :: weight_cutoff = 0.25_8
real(8) :: weight_survive = ONE
! ============================================================================
! MISCELLANEOUS VARIABLES
! Mode to run in (fixed source, eigenvalue, plotting, etc)
integer :: run_mode = NONE
! Restart run
logical :: restart_run = .false.
integer :: restart_batch
character(MAX_FILE_LEN) :: path_input ! Path to input file
character(MAX_FILE_LEN) :: path_cross_sections ! Path to cross_sections.xml
character(MAX_FILE_LEN) :: path_multipole ! Path to wmp library
character(MAX_FILE_LEN) :: path_source = '' ! Path to binary source
character(MAX_FILE_LEN) :: path_state_point ! Path to binary state point
character(MAX_FILE_LEN) :: path_source_point ! Path to binary source point
character(MAX_FILE_LEN) :: path_particle_restart ! Path to particle restart
character(MAX_FILE_LEN) :: path_output = '' ! Path to output directory
! The verbosity controls how much information will be printed to the
! screen and in logs
integer :: verbosity = 7
! Flag for enabling cell overlap checking during transport
logical :: check_overlaps = .false.
integer(8), allocatable :: overlap_check_cnt(:)
! Trace for single particle
logical :: trace
integer :: trace_batch
integer :: trace_gen
integer(8) :: trace_particle
! Particle tracks
logical :: write_all_tracks = .false.
integer, allocatable :: track_identifiers(:,:)
! Particle restart run
logical :: particle_restart_run = .false.
! Number of distribcell maps
integer :: n_maps
! Write out initial source
logical :: write_initial_source = .false.
! ============================================================================
! CMFD VARIABLES
! Main object
type(cmfd_type) :: cmfd
! Is CMFD active
logical :: cmfd_run = .false.
! Timing objects
type(Timer) :: time_cmfd ! timer for whole cmfd calculation
type(Timer) :: time_cmfdbuild ! timer for matrix build
type(Timer) :: time_cmfdsolve ! timer for solver
! Flag for active core map
logical :: cmfd_coremap = .false.
! Flag to reset dhats to zero
logical :: dhat_reset = .false.
! Flag to activate neutronic feedback via source weights
logical :: cmfd_feedback = .false.
! User-defined tally information
integer :: n_cmfd_meshes = 1 ! # of structured meshes
integer :: n_cmfd_tallies = 3 ! # of user-defined tallies
! Adjoint method type
character(len=10) :: cmfd_adjoint_type = 'physical'
! Number of incomplete ilu factorization levels
integer :: cmfd_ilu_levels = 1
! Batch to begin cmfd
integer :: cmfd_begin = 1
! Tally reset list
integer :: n_cmfd_resets
type(SetInt) :: cmfd_reset
! Compute effective downscatter cross section
logical :: cmfd_downscatter = .false.
! Convergence monitoring
logical :: cmfd_power_monitor = .false.
! Cmfd output
logical :: cmfd_write_matrices = .false.
! Run an adjoint calculation (last batch only)
logical :: cmfd_run_adjoint = .false.
! CMFD run logicals
logical :: cmfd_on = .false.
! CMFD display info
character(len=25) :: cmfd_display = 'balance'
! Estimate of spectral radius of CMFD matrices and tolerances
real(8) :: cmfd_spectral = ZERO
real(8) :: cmfd_shift = 1.e6
real(8) :: cmfd_ktol = 1.e-8_8
real(8) :: cmfd_stol = 1.e-8_8
real(8) :: cmfd_atoli = 1.e-10_8
real(8) :: cmfd_rtoli = 1.e-5_8
! Information about state points to be written
integer :: n_state_points = 0
type(SetInt) :: statepoint_batch
! Information about source points to be written
integer :: n_source_points = 0
type(SetInt) :: sourcepoint_batch
! Various output options
logical :: output_summary = .true.
logical :: output_tallies = .true.
! ============================================================================
! RESONANCE SCATTERING VARIABLES
logical :: treat_res_scat = .false. ! is resonance scattering treated?
integer :: n_res_scatterers_total = 0 ! total number of resonant scatterers
type(Nuclide0K), allocatable, target :: nuclides_0K(:) ! 0K nuclides info
!$omp threadprivate(micro_xs, material_xs, fission_bank, n_bank, &
!$omp& trace, thread_id, current_work, matching_bins, &
!$omp& filter_weights)
contains
!===============================================================================
! FREE_MEMORY deallocates and clears all global allocatable arrays in the
! program
!===============================================================================
subroutine free_memory()
integer :: i ! Loop Index
! Deallocate cells, surfaces, materials
if (allocated(cells)) deallocate(cells)
if (allocated(universes)) deallocate(universes)
if (allocated(lattices)) deallocate(lattices)
if (allocated(surfaces)) deallocate(surfaces)
if (allocated(materials)) deallocate(materials)
if (allocated(plots)) deallocate(plots)
! Deallocate geometry debugging information
if (allocated(overlap_check_cnt)) deallocate(overlap_check_cnt)
! Deallocate cross section data, listings, and cache
if (allocated(nuclides)) then
! First call the clear routines
do i = 1, size(nuclides)
call nuclides(i) % clear()
end do
! WARNING: The following statement should work but doesn't under gfortran
! 4.6 because of a bug. Technically, commenting this out leaves a memory
! leak.
! deallocate(nuclides)
end if
if (allocated(nuclides_0K)) then
deallocate(nuclides_0K)
end if
if (allocated(nuclides_MG)) then
deallocate(nuclides_MG)
end if
if (allocated(macro_xs)) then
deallocate(macro_xs)
end if
if (allocated(sab_tables)) deallocate(sab_tables)
if (allocated(micro_xs)) deallocate(micro_xs)
! Deallocate external source
if (allocated(external_source)) deallocate(external_source)
! Deallocate k and entropy
if (allocated(k_generation)) deallocate(k_generation)
if (allocated(entropy)) deallocate(entropy)
if (allocated(entropy_p)) deallocate(entropy_p)
! Deallocate tally-related arrays
if (allocated(global_tallies)) deallocate(global_tallies)
if (allocated(meshes)) deallocate(meshes)
if (allocated(tallies)) deallocate(tallies)
if (allocated(matching_bins)) deallocate(matching_bins)
if (allocated(filter_weights)) deallocate(filter_weights)
! Deallocate fission and source bank and entropy
!$omp parallel
if (allocated(fission_bank)) deallocate(fission_bank)
!$omp end parallel
#ifdef _OPENMP
if (allocated(master_fission_bank)) deallocate(master_fission_bank)
#endif
if (allocated(source_bank)) deallocate(source_bank)
if (allocated(entropy_p)) deallocate(entropy_p)
! Deallocate array of work indices
if (allocated(work_index)) deallocate(work_index)
! Deallocate CMFD
call deallocate_cmfd(cmfd)
! Deallocate tally node lists
call active_analog_tallies % clear()
call active_tracklength_tallies % clear()
call active_current_tallies % clear()
call active_collision_tallies % clear()
call active_tallies % clear()
! Deallocate track_identifiers
if (allocated(track_identifiers)) deallocate(track_identifiers)
! Deallocate dictionaries
call cell_dict % clear()
call universe_dict % clear()
call lattice_dict % clear()
call surface_dict % clear()
call material_dict % clear()
call mesh_dict % clear()
call tally_dict % clear()
call plot_dict % clear()
call nuclide_dict % clear()
call sab_dict % clear()
! Clear statepoint and sourcepoint batch set
call statepoint_batch % clear()
call sourcepoint_batch % clear()
! Deallocate entropy mesh
if (associated(entropy_mesh)) then
if (allocated(entropy_mesh % lower_left)) &
deallocate(entropy_mesh % lower_left)
if (allocated(entropy_mesh % upper_right)) &
deallocate(entropy_mesh % upper_right)
if (allocated(entropy_mesh % width)) deallocate(entropy_mesh % width)
deallocate(entropy_mesh)
end if
! Deallocate ufs
if (allocated(source_frac)) deallocate(source_frac)
if (associated(ufs_mesh)) then
if (allocated(ufs_mesh % lower_left)) deallocate(ufs_mesh % lower_left)
if (allocated(ufs_mesh % upper_right)) &
deallocate(ufs_mesh % upper_right)
if (allocated(ufs_mesh % width)) deallocate(ufs_mesh % width)
deallocate(ufs_mesh)
end if
end subroutine free_memory
end module global