Move openmc_init, initialize_batch, openmc_simulation_finalize to C++

This commit is contained in:
Paul Romano 2018-10-16 19:24:37 -05:00
parent 1c7ebf198e
commit ccf1ced25e
18 changed files with 211 additions and 199 deletions

View file

@ -5,9 +5,6 @@
#include "mpi.h"
#endif
extern "C" void print_usage();
extern "C" void print_version();
namespace openmc {
int parse_command_line(int argc, char* argv[]);

View file

@ -20,7 +20,7 @@ void header(const char* msg, int level);
//! Display information regarding cell overlap checking.
//==============================================================================
extern "C" void print_overlap_check();
void print_overlap_check();
extern "C" void title();

View file

@ -17,6 +17,7 @@ extern "C" const int STREAM_SOURCE;
extern "C" const int STREAM_URR_PTABLE;
extern "C" const int STREAM_VOLUME;
extern "C" const int STREAM_PHOTON;
constexpr int64_t DEFAULT_SEED = 1;
//==============================================================================
//! Generate a pseudo-random number using a linear congruential generator.

View file

@ -56,6 +56,9 @@ void calculate_work();
//! Initialize simulation
extern "C" void openmc_simulation_init_c();
//! Initialize a batch
extern "C" void initialize_batch();
//! Initialize a fission generation
extern "C" void initialize_generation();

View file

@ -38,9 +38,14 @@ private:
// Global variables
//==============================================================================
extern Timer time_active;
extern Timer time_bank;
extern Timer time_bank_sample;
extern Timer time_bank_sendrecv;
extern Timer time_finalize;
extern Timer time_inactive;
extern Timer time_initialize;
extern Timer time_total;
} // namespace openmc

View file

@ -13,7 +13,6 @@ module openmc_api
use math
use message_passing
use nuclide_header
use initialize, only: openmc_init_f
use particle_header
use plot, only: openmc_plot_geometry
use random_lcg, only: openmc_get_seed, openmc_set_seed
@ -63,7 +62,6 @@ module openmc_api
public :: openmc_get_tally_next_id
public :: openmc_global_tallies
public :: openmc_hard_reset
public :: openmc_init_f
public :: openmc_load_nuclide
public :: openmc_material_add_nuclide
public :: openmc_material_get_id
@ -80,7 +78,6 @@ module openmc_api
public :: openmc_plot_geometry
public :: openmc_reset
public :: openmc_set_seed
public :: openmc_simulation_finalize
public :: openmc_simulation_init
public :: openmc_source_bank
public :: openmc_tally_allocate
@ -275,16 +272,10 @@ contains
call k_sum_reset()
! Reset timers
call time_total % reset()
call time_total % reset()
call time_initialize % reset()
call time_read_xs % reset()
call time_unionize % reset()
call time_tallies % reset()
call time_inactive % reset()
call time_active % reset()
call time_transport % reset()
call time_finalize % reset()
call reset_timers()
err = 0

View file

@ -73,7 +73,7 @@ contains
! CMFD_INIT_BATCH handles cmfd options at the start of every batch
!==============================================================================
subroutine cmfd_init_batch()
subroutine cmfd_init_batch() bind(C)
! Check to activate CMFD diffusion and possible feedback
! this guarantees that when cmfd begins at least one batch of tallies are

View file

@ -2,18 +2,8 @@ module initialize
use, intrinsic :: ISO_C_BINDING
#ifdef _OPENMP
use omp_lib
#endif
use bank_header, only: Bank
use constants
use input_xml, only: read_input_xml
use message_passing
use random_lcg, only: openmc_set_seed
use settings
use string, only: ends_with, to_f_string
use timer_header
use string, only: to_f_string
implicit none
@ -42,56 +32,11 @@ module initialize
contains
!===============================================================================
! OPENMC_INIT takes care of all initialization tasks, i.e. reading
! from command line, reading xml input files, initializing random
! number seeds, reading cross sections, initializing starting source,
! setting up timers, etc.
!===============================================================================
function openmc_init_f() result(err) bind(C)
integer(C_INT) :: err
#ifdef _OPENMP
character(MAX_WORD_LEN) :: envvar
#endif
! Start total and initialization timer
call time_total%start()
call time_initialize%start()
#ifdef _OPENMP
! Change schedule of main parallel-do loop if OMP_SCHEDULE is set
call get_environment_variable("OMP_SCHEDULE", envvar)
if (len_trim(envvar) == 0) then
call omp_set_schedule(omp_sched_static, 0)
end if
#endif
! Read command line arguments
call read_command_line()
! Initialize random number generator -- if the user specifies a seed, it
! will be re-initialized later
call openmc_set_seed(DEFAULT_SEED)
! Read XML input files
call read_input_xml()
! Check for particle restart run
if (particle_restart_run) run_mode = MODE_PARTICLE
! Stop initialization timer
call time_initialize%stop()
err = 0
end function openmc_init_f
!===============================================================================
! READ_COMMAND_LINE reads all parameters from the command line
!===============================================================================
subroutine read_command_line()
subroutine read_command_line() bind(C)
! Arguments were already read on C++ side (initialize.cpp). Here we just
! convert the C-style strings to Fortran style

View file

@ -1,12 +1,13 @@
#include "openmc/initialize.h"
#include <cstddef>
#include <cstdlib> // for getenv
#include <cstring>
#include <sstream>
#include <string>
#ifdef _OPENMP
#include "omp.h"
#include <omp.h>
#endif
#include "openmc/capi.h"
@ -14,14 +15,17 @@
#include "openmc/error.h"
#include "openmc/hdf5_interface.h"
#include "openmc/message_passing.h"
#include "openmc/random_lcg.h"
#include "openmc/settings.h"
#include "openmc/simulation.h"
#include "openmc/string_utils.h"
#include "openmc/timer.h"
// data/functions from Fortran side
extern "C" void openmc_init_f();
extern "C" void print_usage();
extern "C" void print_version();
extern "C" void read_command_line();
extern "C" void read_input_xml();
// Paths to various files
extern "C" {
@ -30,6 +34,8 @@ extern "C" {
int openmc_init(int argc, char* argv[], const void* intracomm)
{
using namespace openmc;
#ifdef OPENMC_MPI
// Check if intracomm was passed
MPI_Comm comm;
@ -40,15 +46,40 @@ int openmc_init(int argc, char* argv[], const void* intracomm)
}
// Initialize MPI for C++
openmc::initialize_mpi(comm);
initialize_mpi(comm);
#endif
// Parse command-line arguments
int err = openmc::parse_command_line(argc, argv);
int err = parse_command_line(argc, argv);
if (err) return err;
// Continue with rest of initialization
openmc_init_f();
// Start total and initialization timer
time_total.start();
time_initialize.start();
#ifdef _OPENMP
// If OMP_SCHEDULE is not set, default to a static schedule
char* envvar = std::getenv("OMP_SCHEDULE");
if (!envvar) {
omp_set_schedule(omp_sched_static, 0);
}
#endif
// Read command line arguments
read_command_line();
// Initialize random number generator -- if the user specifies a seed, it
// will be re-initialized later
openmc_set_seed(DEFAULT_SEED);
// Read XML input files
read_input_xml();
// Check for particle restart run
if (settings::particle_restart_run) settings::run_mode = RUN_MODE_PARTICLE;
// Stop initialization timer
time_initialize.stop();
return 0;
}

View file

@ -115,7 +115,7 @@ contains
! geometry, materials, and tallies.
!===============================================================================
subroutine read_input_xml()
subroutine read_input_xml() bind(C)
type(VectorReal), allocatable :: nuc_temps(:) ! List of T to read for each nuclide
type(VectorReal), allocatable :: sab_temps(:) ! List of T to read for each S(a,b)

View file

@ -490,7 +490,7 @@ contains
! initialization, for computation, and for intergeneration synchronization.
!===============================================================================
subroutine print_runtime()
subroutine print_runtime() bind(C)
integer :: n_active
real(8) :: speed_inactive ! # of neutrons/second in inactive batches
@ -501,15 +501,15 @@ contains
call header("Timing Statistics", 6)
! display time elapsed for various sections
write(ou,100) "Total time for initialization", time_initialize % elapsed
write(ou,100) "Total time for initialization", time_initialize_elapsed()
write(ou,100) " Reading cross sections", time_read_xs % elapsed
write(ou,100) "Total time in simulation", time_inactive % elapsed + &
time_active % elapsed
write(ou,100) "Total time in simulation", time_inactive_elapsed() + &
time_active_elapsed()
write(ou,100) " Time in transport only", time_transport % elapsed
if (run_mode == MODE_EIGENVALUE) then
write(ou,100) " Time in inactive batches", time_inactive % elapsed
write(ou,100) " Time in inactive batches", time_inactive_elapsed()
end if
write(ou,100) " Time in active batches", time_active % elapsed
write(ou,100) " Time in active batches", time_active_elapsed()
if (run_mode == MODE_EIGENVALUE) then
write(ou,100) " Time synchronizing fission bank", time_bank_elapsed()
write(ou,100) " Sampling source sites", time_bank_sample_elapsed()
@ -521,29 +521,29 @@ contains
time_cmfdbuild % elapsed
if (cmfd_run) write(ou,100) " Solving matrices", &
time_cmfdsolve % elapsed
write(ou,100) "Total time for finalization", time_finalize % elapsed
write(ou,100) "Total time elapsed", time_total % elapsed
write(ou,100) "Total time for finalization", time_finalize_elapsed()
write(ou,100) "Total time elapsed", time_total_elapsed()
! Calculate particle rate in active/inactive batches
n_active = current_batch - n_inactive
if (restart_run) then
if (restart_batch < n_inactive) then
speed_inactive = real(n_particles * (n_inactive - restart_batch) * &
gen_per_batch) / time_inactive % elapsed
gen_per_batch) / time_inactive_elapsed()
speed_active = real(n_particles * n_active * gen_per_batch) / &
time_active % elapsed
else
speed_inactive = ZERO
speed_active = real(n_particles * (n_batches - restart_batch) * &
gen_per_batch) / time_active % elapsed
gen_per_batch) / time_active_elapsed()
end if
else
if (n_inactive > 0) then
speed_inactive = real(n_particles * n_inactive * gen_per_batch) / &
time_inactive % elapsed
time_inactive_elapsed()
end if
speed_active = real(n_particles * n_active * gen_per_batch) / &
time_active % elapsed
time_active_elapsed()
end if
! display calculation rate
@ -566,7 +566,7 @@ contains
! leakage rate.
!===============================================================================
subroutine print_results()
subroutine print_results() bind(C)
integer :: n ! number of realizations
real(8) :: alpha ! significance level for CI
@ -633,7 +633,7 @@ contains
! tallies and their standard deviations
!===============================================================================
subroutine write_tallies()
subroutine write_tallies() bind(C)
integer :: i ! index in tallies array
integer :: j ! level in tally hierarchy

View file

@ -41,8 +41,7 @@ header(const char* msg, int level) {
//==============================================================================
extern "C" void
print_overlap_check() {
void print_overlap_check() {
#ifdef OPENMC_MPI
std::vector<int64_t> temp(overlap_check_count);
int err = MPI_Reduce(temp.data(), overlap_check_count.data(),

View file

@ -21,8 +21,7 @@ module simulation
use mgxs_interface, only: energy_bins, energy_bin_avg
use nuclide_header, only: micro_xs, n_nuclides
use output, only: header, print_columns, &
print_batch_keff, print_generation, print_runtime, &
print_results, write_tallies
print_batch_keff, print_generation
use particle_header
use photon_header, only: micro_photon_xs, n_elements
use random_lcg, only: set_particle_seed
@ -43,7 +42,6 @@ module simulation
private
public :: openmc_next_batch
public :: openmc_simulation_init
public :: openmc_simulation_finalize
integer(C_INT), parameter :: STATUS_EXIT_NORMAL = 0
integer(C_INT), parameter :: STATUS_EXIT_MAX_BATCH = 1
@ -77,6 +75,10 @@ contains
type(Particle) :: p
integer(8) :: i_work
interface
subroutine initialize_batch() bind(C)
end subroutine
end interface
err = 0
@ -180,50 +182,6 @@ contains
end subroutine initialize_history
!===============================================================================
! INITIALIZE_BATCH
!===============================================================================
subroutine initialize_batch()
integer :: i
! Increment current batch
current_batch = current_batch + 1
if (run_mode == MODE_FIXEDSOURCE) then
call write_message("Simulating batch " // trim(to_str(current_batch)) &
// "...", 6)
end if
! Reset total starting particle weight used for normalizing tallies
total_weight = ZERO
if ((n_inactive > 0 .and. current_batch == 1) .or. &
(restart_run .and. restart_batch < n_inactive .and. current_batch == restart_batch + 1)) then
! Turn on inactive timer
call time_inactive % start()
elseif ((current_batch == n_inactive + 1) .or. &
(restart_run .and. restart_batch > n_inactive .and. current_batch == restart_batch + 1)) then
! Switch from inactive batch timer to active batch timer
call time_inactive % stop()
call time_active % start()
do i = 1, n_tallies
tallies(i) % obj % active = .true.
end do
end if
! check CMFD initialize batch
if (run_mode == MODE_EIGENVALUE) then
if (cmfd_run) call cmfd_init_batch()
end if
! Add user tallies to active tallies list
call setup_active_tallies()
end subroutine initialize_batch
!===============================================================================
! FINALIZE_GENERATION
!===============================================================================
@ -446,27 +404,9 @@ contains
! execution time and results
!===============================================================================
function openmc_simulation_finalize() result(err) bind(C)
integer(C_INT) :: err
subroutine simulation_finalize_f() bind(C)
integer :: i ! loop index
interface
subroutine print_overlap_check() bind(C)
end subroutine print_overlap_check
subroutine broadcast_results() bind(C)
end subroutine broadcast_results
end interface
err = 0
! Skip if simulation was never run
if (.not. simulation_initialized) return
! Stop active batch timer and start finalization timer
call time_active % stop()
call time_finalize % start()
integer :: i ! loop index
! Free up simulation-specific memory
do i = 1, n_materials
@ -480,37 +420,7 @@ contains
deallocate(micro_xs, micro_photon_xs, filter_matches)
!$omp end parallel
! Increment total number of generations
total_gen = total_gen + current_batch*gen_per_batch
#ifdef OPENMC_MPI
call broadcast_results()
#endif
! Write tally results to tallies.out
if (output_tallies .and. master) call write_tallies()
! Deactivate all tallies
if (allocated(tallies)) then
do i = 1, n_tallies
tallies(i) % obj % active = .false.
end do
end if
! Stop timers and show timing statistics
call time_finalize%stop()
call time_total%stop()
if (master) then
if (verbosity >= 6) call print_runtime()
if (verbosity >= 4) call print_results()
end if
if (check_overlaps) call print_overlap_check()
! Reset flags
need_depletion_rx = .false.
simulation_initialized = .false.
end function openmc_simulation_finalize
end subroutine
!===============================================================================
! ALLOCATE_BANKS allocates memory for the fission and source banks

View file

@ -1,12 +1,24 @@
#include "openmc/simulation.h"
#include "openmc/simulation.h"
#include "openmc/capi.h"
#include "openmc/eigenvalue.h"
#include "openmc/error.h"
#include "openmc/message_passing.h"
#include "openmc/output.h"
#include "openmc/settings.h"
#include "openmc/timer.h"
#include "openmc/tallies/tally.h"
#include <algorithm>
#include <string>
// data/functions from Fortran side
extern "C" void cmfd_init_batch();
extern "C" void print_results();
extern "C" void print_runtime();
extern "C" void setup_active_tallies();
extern "C" void simulation_finalize_f();
extern "C" void write_tallies();
// OPENMC_RUN encompasses all the main logic where iterations are performed
// over the batches, generations, and histories in a fixed source or k-eigenvalue
@ -25,6 +37,50 @@ int openmc_run() {
return err;
}
int openmc_simulation_finalize()
{
using namespace openmc;
// Skip if simulation was never run
if (!simulation::simulation_initialized) return 0;
// Stop active batch timer and start finalization timer
time_active.stop();
time_finalize.start();
// Deallocate Fortran variables, set tallies to inactive
simulation_finalize_f();
// Increment total number of generations
simulation::total_gen += simulation::current_batch*settings::gen_per_batch;
#ifdef OPENMC_MPI
broadcast_results()
#endif
// Write tally results to tallies.out
if (settings::output_tallies && mpi::master) write_tallies();
// Deactivate all tallies
for (int i = 1; i <= n_tallies; ++i) {
openmc_tally_set_active(i, false);
}
// Stop timers and show timing statistics
time_finalize.stop();
time_total.stop();
if (mpi::master) {
if (settings::verbosity >= 6) print_runtime();
if (settings::verbosity >= 4) print_results();
}
if (settings::check_overlaps) print_overlap_check();
// Reset flags
simulation::need_depletion_rx = false;
simulation::simulation_initialized = false;
return 0;
}
namespace openmc {
//==============================================================================
@ -72,6 +128,46 @@ void openmc_simulation_init_c()
calculate_work();
}
void initialize_batch()
{
// Increment current batch
++simulation::current_batch;
if (settings::run_mode == RUN_MODE_FIXEDSOURCE) {
int b = simulation::current_batch;
write_message("Simulating batch " + std::to_string(b), 6);
}
// Reset total starting particle weight used for normalizing tallies
total_weight = 0.0;
if ((settings::n_inactive > 0 && simulation::current_batch == 1) ||
(settings::restart_run && simulation::restart_batch < settings::n_inactive &&
simulation::current_batch == simulation::restart_batch + 1)) {
// Turn on inactive timer
time_inactive.start();
} else if ((simulation::current_batch == settings::n_inactive + 1) ||
(settings::restart_run && simulation::restart_batch > settings::n_inactive &&
simulation::current_batch == simulation::restart_batch + 1)) {
// Switch from inactive batch timer to active batch timer
time_inactive.stop();
time_active.start();
for (int i = 1; i <= n_tallies; ++i) {
// TODO: change one-based index
openmc_tally_set_active(i, true);
}
}
// check CMFD initialize batch
if (settings::run_mode == RUN_MODE_EIGENVALUE) {
if (settings::cmfd_run) cmfd_init_batch();
}
// Add user tallies to active tallies list
setup_active_tallies();
}
void initialize_generation()
{
if (settings::run_mode == RUN_MODE_EIGENVALUE) {

View file

@ -391,19 +391,19 @@ contains
! Write out the runtime metrics.
runtime_group = create_group(file_id, "runtime")
call write_dataset(runtime_group, "total initialization", &
time_initialize % get_value())
time_initialize_elapsed())
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())
time_inactive_elapsed() + time_active_elapsed())
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())
time_inactive_elapsed())
end if
call write_dataset(runtime_group, "active batches", &
time_active % get_value())
time_active_elapsed())
if (run_mode == MODE_EIGENVALUE) then
call write_dataset(runtime_group, "synchronizing fission bank", &
time_bank_elapsed())
@ -421,7 +421,7 @@ contains
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 write_dataset(runtime_group, "total", time_total_elapsed())
call close_group(runtime_group)
call file_close(file_id)

View file

@ -3830,7 +3830,7 @@ contains
! SETUP_ACTIVE_TALLIES
!===============================================================================
subroutine setup_active_tallies()
subroutine setup_active_tallies() bind(C)
integer :: i ! loop counter

View file

@ -38,23 +38,37 @@ double Timer::elapsed()
// Global variables
//==============================================================================
Timer time_active;
Timer time_bank;
Timer time_bank_sample;
Timer time_bank_sendrecv;
Timer time_finalize;
Timer time_inactive;
Timer time_initialize;
Timer time_total;
//==============================================================================
// Fortran compatibility
//==============================================================================
extern "C" double time_active_elapsed() { return time_active.elapsed(); }
extern "C" double time_bank_elapsed() { return time_bank.elapsed(); }
extern "C" double time_bank_sample_elapsed() { return time_bank_sample.elapsed(); }
extern "C" double time_bank_sendrecv_elapsed() { return time_bank_sendrecv.elapsed(); }
extern "C" double time_finalize_elapsed() { return time_finalize.elapsed(); }
extern "C" double time_inactive_elapsed() { return time_inactive.elapsed(); }
extern "C" double time_initialize_elapsed() { return time_initialize.elapsed(); }
extern "C" double time_total_elapsed() { return time_total.elapsed(); }
extern "C" void reset_timers()
{
time_active.reset();
time_bank.reset();
time_bank_sample.reset();
time_bank_sendrecv.reset();
time_finalize.reset();
time_initialize.reset();
time_total.reset();
}
} // namespace openmc

View file

@ -7,6 +7,10 @@ module timer_header
implicit none
interface
function time_active_elapsed() result(t) bind(C)
import C_DOUBLE
real(C_DOUBLE) :: t
end function
function time_bank_elapsed() result(t) bind(C)
import C_DOUBLE
real(C_DOUBLE) :: t
@ -19,6 +23,22 @@ module timer_header
import C_DOUBLE
real(C_DOUBLE) :: t
end function
function time_finalize_elapsed() result(t) bind(C)
import C_DOUBLE
real(C_DOUBLE) :: t
end function
function time_inactive_elapsed() result(t) bind(C)
import C_DOUBLE
real(C_DOUBLE) :: t
end function
function time_initialize_elapsed() result(t) bind(C)
import C_DOUBLE
real(C_DOUBLE) :: t
end function
function time_total_elapsed() result(t) bind(C)
import C_DOUBLE
real(C_DOUBLE) :: t
end function
subroutine reset_timers() bind(C)
end subroutine
end interface