diff --git a/docs/source/usersguide/output/statepoint.rst b/docs/source/usersguide/output/statepoint.rst index 225161965..95a3d842c 100644 --- a/docs/source/usersguide/output/statepoint.rst +++ b/docs/source/usersguide/output/statepoint.rst @@ -248,7 +248,7 @@ if run_mode == 'k-eigenvalue': Accumulated sum and sum-of-squares for each global tally. The compound type has fields named ``sum`` and ``sum_sq``. -**tallies_present** (*int*) +**/tallies_present** (*int*) Flag indicated if tallies are present in the file. @@ -260,3 +260,69 @@ if (run_mode == 'k-eigenvalue' and source_present > 0) ``wgt``, ``xyz``, ``uvw``, ``E``, ``g``, and ``delayed_group``, which represent the weight, position, direction, energy, energy group, and delayed_group of the source particle, respectively. + +**/runtime/total initialization** (*double*) + + Time (in seconds on the master process) spent reading inputs, allocating + arrays, etc. + +**/runtime/reading cross sections** (*double*) + + Time (in seconds on the master process) spent loading cross section + libraries (this is a subset of initialization). + +**/runtime/simulation** (*double*) + + Time (in seconds on the master process) spent between initialization and + finalization. + +**/runtime/transport** (*double*) + + Time (in seconds on the master process) spent transporting particles. + +**/runtime/inactive batches** (*double*) + + Time (in seconds on the master process) spent in the inactive batches + (including non-transport activities like communcating sites). + +**/runtime/active batches** (*double*) + + Time (in seconds on the master process) spent in the active batches + (including non-transport activities like communicating sites). + +**/runtime/synchronizing fission bank** (*double*) + + Time (in seconds on the master process) spent sampling source particles + from fission sites and communicating them to other processes for load + balancing. + +**/runtime/sampling source sites** (*double*) + + Time (in seconds on the master process) spent sampling source particles + from fission sites. + +**/runtime/SEND-RECV source sites** (*double*) + + Time (in seconds on the master process) spent communicating source sites + between processes for load balancing. + +**/runtime/accumulating tallies** (*double*) + + Time (in seconds on the master process) spent communicating tally results + and evaluating their statistics. + +**/runtime/CMFD** (*double*) + + Time (in seconds on the master process) spent evaluating CMFD. + +**/runtime/CMFD building matrices** (*double*) + + Time (in seconds on the master process) spent buliding CMFD matrices. + +**/runtime/CMFD solving matrices** (*double*) + + Time (in seconds on the master process) spent solving CMFD matrices. + +**/runtime/total** (*double*) + + Total time spent (in seconds on the master process) in the program. diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 1644e44ab..693400ad6 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -68,6 +68,9 @@ class StatePoint(object): Working directory for simulation run_mode : str Simulation run mode, e.g. 'k-eigenvalue' + runtime : dict + Dictionary whose keys are strings describing various runtime metrics + and whose values are time values in seconds. seed : Integral Pseudorandom number generator seed source : ndarray of compound datatype @@ -101,8 +104,9 @@ class StatePoint(object): raise IOError('{} is not a statepoint file.'.format(filename)) except AttributeError: raise IOError('Could not read statepoint file. This most likely ' - 'means the statepoint file was produced by a different ' - 'version of OpenMC than the one you are using.') + 'means the statepoint file was produced by a ' + 'different version of OpenMC than the one you are ' + 'using.') if self._f['revision'].value != 15: raise IOError('Statepoint file has a file revision of {} ' 'which is not consistent with the revision this ' @@ -311,6 +315,11 @@ class StatePoint(object): def run_mode(self): return self._f['run_mode'].value.decode() + @property + def runtime(self): + return {name: dataset.value + for name, dataset in self._f['runtime'].items()} + @property def seed(self): return self._f['seed'].value diff --git a/src/state_point.F90 b/src/state_point.F90 index 6c0e309e2..4348ad331 100644 --- a/src/state_point.F90 +++ b/src/state_point.F90 @@ -49,10 +49,8 @@ contains integer, allocatable :: id_array(:) integer, allocatable :: key_array(:) integer(HID_T) :: file_id - integer(HID_T) :: cmfd_group - integer(HID_T) :: tallies_group, tally_group - integer(HID_T) :: meshes_group, mesh_group - integer(HID_T) :: filter_group + integer(HID_T) :: cmfd_group, tallies_group, tally_group, meshes_group, & + mesh_group, filter_group, runtime_group character(20), allocatable :: str_array(:) character(MAX_FILE_LEN) :: filename type(RegularMesh), pointer :: meshp @@ -133,13 +131,13 @@ contains call write_dataset(file_id, "cmfd_on", 1) cmfd_group = create_group(file_id, "cmfd") - call write_dataset(cmfd_group, "indices", cmfd%indices) - call write_dataset(cmfd_group, "k_cmfd", cmfd%k_cmfd) - call write_dataset(cmfd_group, "cmfd_src", cmfd%cmfd_src) - call write_dataset(cmfd_group, "cmfd_entropy", cmfd%entropy) - call write_dataset(cmfd_group, "cmfd_balance", cmfd%balance) - call write_dataset(cmfd_group, "cmfd_dominance", cmfd%dom) - call write_dataset(cmfd_group, "cmfd_srccmp", cmfd%src_cmp) + call write_dataset(cmfd_group, "indices", cmfd % indices) + call write_dataset(cmfd_group, "k_cmfd", cmfd % k_cmfd) + call write_dataset(cmfd_group, "cmfd_src", cmfd % cmfd_src) + call write_dataset(cmfd_group, "cmfd_entropy", cmfd % entropy) + call write_dataset(cmfd_group, "cmfd_balance", cmfd % balance) + call write_dataset(cmfd_group, "cmfd_dominance", cmfd % dom) + call write_dataset(cmfd_group, "cmfd_srccmp", cmfd % src_cmp) call close_group(cmfd_group) else call write_dataset(file_id, "cmfd_on", 0) @@ -155,18 +153,18 @@ contains if (n_meshes > 0) then ! Print list of mesh IDs - current => mesh_dict%keys() + current => mesh_dict % keys() allocate(id_array(n_meshes)) allocate(key_array(n_meshes)) i = 1 do while (associated(current)) - key_array(i) = current%key - id_array(i) = current%value + key_array(i) = current % key + id_array(i) = current % value ! Move to next mesh - next => current%next + next => current % next deallocate(current) current => next i = i + 1 @@ -180,16 +178,17 @@ contains ! Write information for meshes MESH_LOOP: do i = 1, n_meshes meshp => meshes(id_array(i)) - mesh_group = create_group(meshes_group, "mesh " // trim(to_str(meshp%id))) + mesh_group = create_group(meshes_group, "mesh " & + // trim(to_str(meshp % id))) - select case (meshp%type) + select case (meshp % type) case (MESH_REGULAR) call write_dataset(mesh_group, "type", "regular") end select - call write_dataset(mesh_group, "dimension", meshp%dimension) - call write_dataset(mesh_group, "lower_left", meshp%lower_left) - call write_dataset(mesh_group, "upper_right", meshp%upper_right) - call write_dataset(mesh_group, "width", meshp%width) + call write_dataset(mesh_group, "dimension", meshp % dimension) + call write_dataset(mesh_group, "lower_left", meshp % lower_left) + call write_dataset(mesh_group, "upper_right", meshp % upper_right) + call write_dataset(mesh_group, "width", meshp % width) call close_group(mesh_group) end do MESH_LOOP @@ -211,7 +210,7 @@ contains ! Write all tally information except results do i = 1, n_tallies tally => tallies(i) - key_array(i) = tally%id + key_array(i) = tally % id id_array(i) = i end do @@ -226,9 +225,9 @@ contains ! Get pointer to tally tally => tallies(i) tally_group = create_group(tallies_group, "tally " // & - trim(to_str(tally%id))) + trim(to_str(tally % id))) - select case(tally%estimator) + select case(tally % estimator) case (ESTIMATOR_ANALOG) call write_dataset(tally_group, "estimator", "analog") case (ESTIMATOR_TRACKLENGTH) @@ -236,16 +235,17 @@ contains case (ESTIMATOR_COLLISION) call write_dataset(tally_group, "estimator", "collision") end select - call write_dataset(tally_group, "n_realizations", tally%n_realizations) - call write_dataset(tally_group, "n_filters", tally%n_filters) + call write_dataset(tally_group, "n_realizations", & + tally % n_realizations) + call write_dataset(tally_group, "n_filters", tally % n_filters) ! Write filter information - FILTER_LOOP: do j = 1, tally%n_filters + FILTER_LOOP: do j = 1, tally % n_filters filter_group = create_group(tally_group, "filter " // & trim(to_str(j))) ! Write name of type - select case (tally%filters(j)%type) + select case (tally % filters(j) % type) case(FILTER_UNIVERSE) call write_dataset(filter_group, "type", "universe") case(FILTER_MATERIAL) @@ -274,36 +274,37 @@ contains call write_dataset(filter_group, "type", "delayedgroup") end select - call write_dataset(filter_group, "n_bins", tally%filters(j)%n_bins) + call write_dataset(filter_group, "n_bins", & + tally % filters(j) % n_bins) if (tally % filters(j) % type == FILTER_ENERGYIN .or. & tally % filters(j) % type == FILTER_ENERGYOUT .or. & tally % filters(j) % type == FILTER_MU .or. & tally % filters(j) % type == FILTER_POLAR .or. & tally % filters(j) % type == FILTER_AZIMUTHAL) then call write_dataset(filter_group, "bins", & - tally%filters(j)%real_bins) + tally % filters(j) % real_bins) else call write_dataset(filter_group, "bins", & - tally%filters(j)%int_bins) + tally % filters(j) % int_bins) end if call close_group(filter_group) end do FILTER_LOOP ! Set up nuclide bin array and then write - allocate(str_array(tally%n_nuclide_bins)) - NUCLIDE_LOOP: do j = 1, tally%n_nuclide_bins - if (tally%nuclide_bins(j) > 0) then + allocate(str_array(tally % n_nuclide_bins)) + NUCLIDE_LOOP: do j = 1, tally % n_nuclide_bins + if (tally % nuclide_bins(j) > 0) then ! Get index in cross section listings for this nuclide - i_list = nuclides(tally%nuclide_bins(j))%listing + i_list = nuclides(tally % nuclide_bins(j)) % listing ! Determine position of . in alias string (e.g. "U-235.71c"). If ! no . is found, just use the entire string. - i_xs = index(xs_listings(i_list)%alias, '.') + i_xs = index(xs_listings(i_list) % alias, '.') if (i_xs > 0) then - str_array(j) = xs_listings(i_list)%alias(1:i_xs - 1) + str_array(j) = xs_listings(i_list) % alias(1:i_xs - 1) else - str_array(j) = xs_listings(i_list)%alias + str_array(j) = xs_listings(i_list) % alias end if else str_array(j) = 'total' @@ -312,32 +313,33 @@ contains call write_dataset(tally_group, "nuclides", str_array) deallocate(str_array) - call write_dataset(tally_group, "n_score_bins", tally%n_score_bins) - allocate(str_array(size(tally%score_bins))) - do j = 1, size(tally%score_bins) - str_array(j) = reaction_name(tally%score_bins(j)) + call write_dataset(tally_group, "n_score_bins", tally % n_score_bins) + allocate(str_array(size(tally % score_bins))) + do j = 1, size(tally % score_bins) + str_array(j) = reaction_name(tally % score_bins(j)) end do call write_dataset(tally_group, "score_bins", str_array) - call write_dataset(tally_group, "n_user_score_bins", tally%n_user_score_bins) + call write_dataset(tally_group, "n_user_score_bins", & + tally % n_user_score_bins) deallocate(str_array) ! Write explicit moment order strings for each score bin k = 1 - allocate(str_array(tally%n_score_bins)) - MOMENT_LOOP: do j = 1, tally%n_user_score_bins - select case(tally%score_bins(k)) + allocate(str_array(tally % n_score_bins)) + MOMENT_LOOP: do j = 1, tally % n_user_score_bins + select case(tally % score_bins(k)) case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N) - str_array(k) = 'P' // trim(to_str(tally%moment_order(k))) + str_array(k) = 'P' // trim(to_str(tally % moment_order(k))) k = k + 1 case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN) - do n_order = 0, tally%moment_order(k) + do n_order = 0, tally % moment_order(k) str_array(k) = 'P' // trim(to_str(n_order)) k = k + 1 end do case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, & SCORE_TOTAL_YN) - do n_order = 0, tally%moment_order(k) + do n_order = 0, tally % moment_order(k) do nm_order = -n_order, n_order str_array(k) = 'Y' // trim(to_str(n_order)) // ',' // & trim(to_str(nm_order)) @@ -389,8 +391,9 @@ contains tally => tallies(i) ! Write sum and sum_sq for each bin - tally_group = open_group(tallies_group, "tally " // to_str(tally%id)) - call write_dataset(tally_group, "results", tally%results) + tally_group = open_group(tallies_group, "tally " & + // to_str(tally % id)) + call write_dataset(tally_group, "results", tally % results) call close_group(tally_group) end do TALLY_RESULTS @@ -400,13 +403,45 @@ contains end if call close_group(tallies_group) + + ! Write out the runtime metrics. + runtime_group = create_group(file_id, "runtime") + call write_dataset(runtime_group, "total initialization", & + time_initialize % get_value()) + call write_dataset(runtime_group, "reading cross sections", & + time_read_xs % get_value()) + call write_dataset(runtime_group, "simulation", & + time_inactive % get_value() + time_active % get_value()) + call write_dataset(runtime_group, "transport", & + time_transport % get_value()) + if (run_mode == MODE_EIGENVALUE) then + call write_dataset(runtime_group, "inactive batches", & + time_inactive % get_value()) + end if + call write_dataset(runtime_group, "active batches", & + time_active % get_value()) + if (run_mode == MODE_EIGENVALUE) then + call write_dataset(runtime_group, "synchronizing fission bank", & + time_bank % get_value()) + call write_dataset(runtime_group, "sampling source sites", & + time_bank_sample % get_value()) + call write_dataset(runtime_group, "SEND-RECV source sites", & + time_bank_sendrecv % get_value()) + end if + call write_dataset(runtime_group, "accumulating tallies", & + time_tallies % get_value()) + if (cmfd_run) then + call write_dataset(runtime_group, "CMFD", time_cmfd % get_value()) + call write_dataset(runtime_group, "CMFD building matrices", & + time_cmfdbuild % get_value()) + call write_dataset(runtime_group, "CMFD solving matrices", & + time_cmfdsolve % get_value()) + end if + call write_dataset(runtime_group, "total", time_total % get_value()) + call close_group(runtime_group) + call file_close(file_id) end if - - if (master .and. n_tallies > 0) then - deallocate(id_array) - end if - end subroutine write_state_point !=============================================================================== diff --git a/src/summary.F90 b/src/summary.F90 index b33546e66..35c62ae03 100644 --- a/src/summary.F90 +++ b/src/summary.F90 @@ -717,63 +717,4 @@ contains end subroutine write_tallies -!=============================================================================== -! WRITE_TIMING -!=============================================================================== - - subroutine write_timing(file_id) - integer(HID_T), intent(in) :: file_id - - integer(8) :: total_particles - integer(HID_T) :: time_group - real(8) :: speed - - time_group = create_group(file_id, "timing") - - ! Write timing data - call write_dataset(time_group, "time_initialize", time_initialize%elapsed) - call write_dataset(time_group, "time_read_xs", time_read_xs%elapsed) - call write_dataset(time_group, "time_transport", time_transport%elapsed) - call write_dataset(time_group, "time_bank", time_bank%elapsed) - call write_dataset(time_group, "time_bank_sample", time_bank_sample%elapsed) - call write_dataset(time_group, "time_bank_sendrecv", time_bank_sendrecv%elapsed) - call write_dataset(time_group, "time_tallies", time_tallies%elapsed) - call write_dataset(time_group, "time_inactive", time_inactive%elapsed) - call write_dataset(time_group, "time_active", time_active%elapsed) - call write_dataset(time_group, "time_finalize", time_finalize%elapsed) - call write_dataset(time_group, "time_total", time_total%elapsed) - - ! Add descriptions to timing data - call write_attribute_string(time_group, "time_initialize", "description", & - "Total time elapsed for initialization (s)") - call write_attribute_string(time_group, "time_read_xs", "description", & - "Time reading cross-section libraries (s)") - call write_attribute_string(time_group, "time_transport", "description", & - "Time in transport only (s)") - call write_attribute_string(time_group, "time_bank", "description", & - "Total time synchronizing fission bank (s)") - call write_attribute_string(time_group, "time_bank_sample", "description", & - "Time between generations sampling source sites (s)") - call write_attribute_string(time_group, "time_bank_sendrecv", "description", & - "Time between generations SEND/RECVing source sites (s)") - call write_attribute_string(time_group, "time_tallies", "description", & - "Time between batches accumulating tallies (s)") - call write_attribute_string(time_group, "time_inactive", "description", & - "Total time in inactive batches (s)") - call write_attribute_string(time_group, "time_active", "description", & - "Total time in active batches (s)") - call write_attribute_string(time_group, "time_finalize", "description", & - "Total time for finalization (s)") - call write_attribute_string(time_group, "time_total", "description", & - "Total time elapsed (s)") - - ! Write calculation rate - total_particles = n_particles * n_batches * gen_per_batch - speed = real(total_particles) / (time_inactive%elapsed + & - time_active%elapsed) - call write_dataset(time_group, "neutrons_per_second", speed) - - call close_group(time_group) - end subroutine write_timing - end module summary