Merge pull request #180 from mit-crpg/hdf5_parallel

PHDF5 Collective/Independent Calls
This commit is contained in:
Paul Romano 2013-06-09 15:37:47 -07:00
commit 47e4dbb01d
3 changed files with 421 additions and 77 deletions

View file

@ -385,13 +385,49 @@ contains
! HDF5_WRITE_STRING writes string data
!===============================================================================
subroutine hdf5_write_string(group, name, buffer)
subroutine hdf5_write_string(group, name, buffer, length)
integer(HID_T), intent(in) :: group ! name of group
character(*), intent(in) :: name ! name of data
character(*), intent(in) :: buffer ! data to write
integer, intent(in) :: length
call h5ltmake_dataset_string_f(group, name, buffer, hdf5_err)
character(len=length), dimension(1) :: str_tmp
! Fortran 2003 implementation not compatible with IBM compiler Feb 2013
! type(c_ptr), dimension(1), target :: wdata
! character(len=length, kind=c_char), dimension(1), target :: c_str
! dims1(1) = 1
! call h5screate_simple_f(1, dims1, dspace, hdf5_err)
! call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err)
! c_str(1) = buffer
! wdata(1) = c_loc(c_str(1))
! f_ptr = c_loc(wdata(1))
! Number of strings to write
dims1(1) = 1
! Insert null character at end of string when writing
call h5tset_strpad_f(H5T_STRING, H5T_STR_NULLPAD_F, hdf5_err)
! Create the dataspace and dataset
call h5screate_simple_f(1, dims1, dspace, hdf5_err)
call h5dcreate_f(group, name, H5T_STRING, dspace, dset, hdf5_err)
! Set up dimesnions of string to write
dims2 = (/length, 1/) ! full array of strings to write
dims1(1) = length ! length of string
! Copy over string buffer to a rank 1 array
str_tmp(1) = buffer
! Write the variable dataset
call h5dwrite_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, &
mem_space_id=dspace)
! Close all
call h5dclose_f(dset, hdf5_err)
call h5sclose_f(dspace, hdf5_err)
end subroutine hdf5_write_string
@ -530,6 +566,219 @@ contains
end subroutine hdf5_read_string
# ifdef MPI
!===============================================================================
! HDF5_PARALLEL_READ_INTEGER reads interger scalar data in parallel
!===============================================================================
subroutine hdf5_parallel_read_integer(group, name, buffer, p_type)
integer(HID_T), intent(in) :: group ! name of group
character(*), intent(in) :: name ! name of data
integer, target, intent(inout) :: buffer ! read data to here
integer, intent(in) :: p_type ! independent or collective I/O
! Set up dimension
dims1(1) = 1
! Create property list for independent or collective read
call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err)
! Set independent or collective option
call h5pset_dxpl_mpio_f(plist, p_type, hdf5_err)
! Open dataset
call h5dopen_f(group, name, dset, hdf5_err)
! Read data
f_ptr = c_loc(buffer)
call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist)
! Close dataset and property list
call h5dclose_f(dset, hdf5_err)
call h5pclose_f(plist, hdf5_err)
end subroutine hdf5_parallel_read_integer
!===============================================================================
! HDF5_PARALLEL_READ_INTEGER_1DARRAY reads integer 1-D array in parallel
!===============================================================================
subroutine hdf5_parallel_read_integer_1Darray(group, name, buffer, length, &
p_type)
integer(HID_T), intent(in) :: group ! name of group
character(*), intent(in) :: name ! name of data
integer, intent(in) :: length ! length of array
integer, target, intent(inout) :: buffer(length) ! read data to here
integer, intent(in) :: p_type ! independent or collective I/O
! Create property list for independent or collective read
call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err)
! Set independent or collective option
call h5pset_dxpl_mpio_f(plist, p_type, hdf5_err)
! Open dataset
call h5dopen_f(group, name, dset, hdf5_err)
! Read data
f_ptr = c_loc(buffer(1))
call h5dread_f(dset, H5T_NATIVE_INTEGER, f_ptr, hdf5_err, xfer_prp=plist)
! Close dataset and property list
call h5dclose_f(dset, hdf5_err)
call h5pclose_f(plist, hdf5_err)
end subroutine hdf5_parallel_read_integer_1Darray
!===============================================================================
! HDF5_PARALLEL_READ_LONG read long integer scalar data in parallel
!===============================================================================
subroutine hdf5_parallel_read_long(group, name, buffer, long_type, p_type)
integer(HID_T), intent(in) :: group ! name of group
character(*), intent(in) :: name ! name of data
integer(8), target, intent(out) :: buffer ! read data to here
integer(HID_T), intent(in) :: long_type ! long integer type
integer, intent(in) :: p_type ! independent or collective I/O
! Create property list for independent or collective read
call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err)
! Set independent or collective option
call h5pset_dxpl_mpio_f(plist, p_type, hdf5_err)
! Open dataset
call h5dopen_f(group, name, dset, hdf5_err)
! Read data
f_ptr = c_loc(buffer)
call h5dread_f(dset, long_type, f_ptr, hdf5_err, xfer_prp=plist)
! Close dataset and property list
call h5dclose_f(dset, hdf5_err)
call h5pclose_f(plist, hdf5_err)
end subroutine hdf5_parallel_read_long
!===============================================================================
! HDF5_PARALLEL_READ_DOUBLE reads double precision scalar data in parallel
!===============================================================================
subroutine hdf5_parallel_read_double(group, name, buffer, p_type)
integer(HID_T), intent(in) :: group ! name of group
character(*), intent(in) :: name ! name of data
real(8), target, intent(inout) :: buffer ! read data to here
integer, intent(in) :: p_type ! independent or collective I/O
! Create property list for independent or collective read
call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err)
! Set independent or collective option
call h5pset_dxpl_mpio_f(plist, p_type, hdf5_err)
! Open dataset
call h5dopen_f(group, name, dset, hdf5_err)
! Read data
f_ptr = c_loc(buffer)
call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist)
! Close dataset and property list
call h5dclose_f(dset, hdf5_err)
call h5pclose_f(plist, hdf5_err)
end subroutine hdf5_parallel_read_double
!===============================================================================
! HDF5_PARLLEL_READ_DOUBLE_1DARRAY reads double precision 1-D array in parallel
!===============================================================================
subroutine hdf5_parallel_read_double_1Darray(group, name, buffer, length, &
p_type)
integer(HID_T), intent(in) :: group ! name of group
integer, intent(in) :: length ! length of array
integer, intent(in) :: p_type ! indepedent or collective I/O
character(*), intent(in) :: name ! name of data
real(8), target, intent(inout) :: buffer(length) ! read data to here
! Create property list for independent or collective read
call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err)
! Set independent or collective option
call h5pset_dxpl_mpio_f(plist, p_type, hdf5_err)
! Open dataset
call h5dopen_f(group, name, dset, hdf5_err)
! Read data
f_ptr = c_loc(buffer(1))
call h5dread_f(dset, H5T_NATIVE_DOUBLE, f_ptr, hdf5_err, xfer_prp=plist)
! Close dataset and property list
call h5dclose_f(dset, hdf5_err)
call h5pclose_f(plist, hdf5_err)
end subroutine hdf5_parallel_read_double_1Darray
!===============================================================================
! HDF5_PARALLEL_READ_STRING reads string data
!===============================================================================
subroutine hdf5_parallel_read_string(group, name, buffer, length, p_type)
integer(HID_T), intent(in) :: group ! name of group
character(*), intent(in) :: name ! name of data
character(*), target, intent(inout) :: buffer ! read data to here
integer, intent(in) :: p_type ! independent or collective IO
integer, intent(in) :: length ! length of string
character(len=length), dimension(1) :: str_tmp
! Fortran 2003 implementation not compatible with IBM Feb 2013 compiler
! type(c_ptr), dimension(1), target :: buf_ptr
! character(len=length, kind=c_char), pointer :: chr_ptr
! f_ptr = c_loc(buf_ptr(1))
! call h5dread_f(dset, H5T_STRING, f_ptr, hdf5_err, xfer_prp=plist)
! call c_f_pointer(buf_ptr(1), chr_ptr)
! buffer = chr_ptr
! nullify(chr_ptr)
! Create property list for independent or collective read
call h5pcreate_f(H5P_DATASET_XFER_F, plist, hdf5_err)
! Set independent or collective option
call h5pset_dxpl_mpio_f(plist, p_type, hdf5_err)
! Open dataset
call h5dopen_f(group, name, dset, hdf5_err)
! Get dataspace to read
call h5dget_space_f(dset, dspace, hdf5_err)
! Set dimensions
dims2 = (/length, 1/)
dims1(1) = length
! Read in the data
call h5dread_vl_f(dset, H5T_STRING, str_tmp, dims2, dims1, hdf5_err, &
mem_space_id=dspace, xfer_prp = plist)
! Copy over buffer
buffer = str_tmp(1)
! Close dataset and property list
call h5dclose_f(dset, hdf5_err)
call h5pclose_f(plist, hdf5_err)
end subroutine hdf5_parallel_read_string
# endif
#endif
end module hdf5_interface

View file

@ -184,11 +184,12 @@ contains
! READ_DOUBLE reads double precision scalar data
!===============================================================================
subroutine read_double(buffer, name, group)
subroutine read_double(buffer, name, group, option)
real(8), intent(inout) :: buffer ! read data to here
character(*), intent(in) :: name ! name for data
character(*), intent(in), optional :: group ! HDF5 group name
character(*), intent(in), optional :: option ! type of read
#ifdef HDF5
! Check if HDF5 group should be created/opened
@ -197,10 +198,24 @@ contains
else
temp_group = hdf5_fh
endif
! Read the data
# ifdef MPI
! Check for option for reading default is independent
if (present(option)) then
if (option == 'collective') then
call hdf5_parallel_read_double(temp_group, name, buffer, &
H5FD_MPIO_COLLECTIVE_F)
else
call hdf5_parallel_read_double(temp_group, name, buffer, &
H5FD_MPIO_INDEPENDENT_F)
end if
else
! Standard read call
call hdf5_read_double(temp_group, name, buffer)
end if
# else
! Read the data serial
call hdf5_read_double(temp_group, name, buffer)
# endif
! Check if HDf5 group should be closed
if (present(group)) call hdf5_close_group()
#elif MPI
@ -247,12 +262,13 @@ contains
! READ_DOUBLE_1DARRAY reads double precision 1-D array data
!===============================================================================
subroutine read_double_1Darray(buffer, name, group, length)
subroutine read_double_1Darray(buffer, name, group, length, option)
integer, intent(in) :: length ! length of array to read
real(8), intent(inout) :: buffer(:) ! read data to here
character(*), intent(in) :: name ! name of data
character(*), intent(in), optional :: group ! HDF5 group name
character(*), intent(in), optional :: option ! read option
#ifdef HDF5
! Check if HDF5 group should be created/opened
@ -261,10 +277,24 @@ contains
else
temp_group = hdf5_fh
endif
! Read the data
# ifdef MPI
! Check for option for reading default is independent
if (present(option)) then
if (option == 'collective') then
call hdf5_parallel_read_double_1Darray(temp_group, name, buffer, &
length, H5FD_MPIO_COLLECTIVE_F)
else
call hdf5_parallel_read_double_1Darray(temp_group, name, buffer, &
length, H5FD_MPIO_INDEPENDENT_F)
end if
else
! Standard read call
call hdf5_read_double_1Darray(temp_group, name, buffer, length)
end if
# else
! Read the data serial
call hdf5_read_double_1Darray(temp_group, name, buffer, length)
# endif
! Check if HDF5 group should be closed
if (present(group)) call hdf5_close_group()
#elif MPI
@ -372,11 +402,12 @@ contains
! READ_INTEGER reads integer scalar data
!===============================================================================
subroutine read_integer(buffer, name, group)
subroutine read_integer(buffer, name, group, option)
integer, intent(inout) :: buffer ! read data to here
character(*), intent(in) :: name ! name of data
character(*), intent(in), optional :: group ! HDF5 group name
character(*), intent(in), optional :: option ! read option
#ifdef HDF5
! Check if HDF5 group should be created/opened
@ -385,10 +416,24 @@ contains
else
temp_group = hdf5_fh
endif
! Read the data
# ifdef MPI
! Check for option for reading default is independent
if (present(option)) then
if (option == 'collective') then
call hdf5_parallel_read_integer(temp_group, name, buffer, &
H5FD_MPIO_COLLECTIVE_F)
else
call hdf5_parallel_read_integer(temp_group, name, buffer, &
H5FD_MPIO_INDEPENDENT_F)
end if
else
! Standard read call
call hdf5_read_integer(temp_group, name, buffer)
end if
# else
! Read the data serial
call hdf5_read_integer(temp_group, name, buffer)
# endif
! Check if HDF5 group should be closed
if (present(group)) call hdf5_close_group()
#elif MPI
@ -436,12 +481,13 @@ contains
! READ_INTEGER_1DARRAY reads integer 1-D array data
!===============================================================================
subroutine read_integer_1Darray(buffer, name, group, length)
subroutine read_integer_1Darray(buffer, name, group, length, option)
integer, intent(in) :: length ! length of array to read
integer, intent(inout) :: buffer(:) ! read data to here
character(*), intent(in) :: name ! name of data
character(*), intent(in), optional :: group ! HDF5 group name
character(*), intent(in), optional :: option ! read option
#ifdef HDF5
! Check if HDF5 group should be created/opened
@ -450,9 +496,24 @@ contains
else
temp_group = hdf5_fh
endif
! Read the data
# ifdef MPI
! Check for option for reading default is independent
if (present(option)) then
if (option == 'collective') then
call hdf5_parallel_read_integer_1Darray(temp_group, name, buffer, &
length, H5FD_MPIO_COLLECTIVE_F)
else
call hdf5_parallel_read_integer_1Darray(temp_group, name, buffer, &
length, H5FD_MPIO_INDEPENDENT_F)
end if
else
! Standard read call
call hdf5_read_integer_1Darray(temp_group, name, buffer, length)
end if
# else
! Read the data serial
call hdf5_read_integer_1Darray(temp_group, name, buffer, length)
# endif
if (present(group)) call hdf5_close_group()
#elif MPI
call mpi_read_integer_1Darray(mpi_fh, buffer, length)
@ -559,11 +620,12 @@ contains
! READ_LONG reads long integer scalar data
!===============================================================================
subroutine read_long(buffer, name, group)
subroutine read_long(buffer, name, group, option)
integer(8), intent(inout) :: buffer ! read data to here
character(*), intent(in) :: name ! name of data
character(*), intent(in), optional :: group ! HDF5 group name
character(*), intent(in), optional :: option ! read option
#ifdef HDF5
! Check if HDF5 group should be created/opened
@ -572,10 +634,24 @@ contains
else
temp_group = hdf5_fh
endif
! Read the data
# ifdef MPI
! Check for option for reading default is independent
if (present(option)) then
if (option == 'collective') then
call hdf5_parallel_read_long(temp_group, name, buffer, &
hdf5_integer8_t, H5FD_MPIO_COLLECTIVE_F)
else
call hdf5_parallel_read_long(temp_group, name, buffer, &
hdf5_integer8_t, H5FD_MPIO_INDEPENDENT_F)
end if
else
! Standard read call
call hdf5_read_long(temp_group, name, buffer, hdf5_integer8_t)
end if
# else
! Read the data serial
call hdf5_read_long(temp_group, name, buffer, hdf5_integer8_t)
# endif
! Check if HDF5 group should be closed
if (present(group)) call hdf5_close_group()
#elif MPI
@ -611,7 +687,7 @@ contains
endif
! Write the data
call hdf5_write_string(temp_group, name, buffer)
call hdf5_write_string(temp_group, name, buffer, len(buffer))
! Check if HDf5 group should be closed
if (present(group)) call hdf5_close_group()
@ -631,17 +707,17 @@ contains
! READ_STRING reads string data
!===============================================================================
subroutine read_string(buffer, name, group)
subroutine read_string(buffer, name, group, option)
character(*), intent(inout) :: buffer ! read data to here
character(*), intent(in) :: name ! name of data
character(*), intent(in), optional :: group ! HDF5 group name
character(*), intent(in), optional :: option ! read option
#ifndef HDF5
# ifdef MPI
integer :: n ! length of string to read to
# endif
#endif
! Length of string buffer to read
n = len(buffer)
#ifdef HDF5
! Check if HDF5 group should be created/opened
@ -650,17 +726,28 @@ contains
else
temp_group = hdf5_fh
endif
! Read the data
# ifdef MPI
! Check for option for reading default is independent
if (present(option)) then
if (option == 'collective') then
call hdf5_parallel_read_string(temp_group, name, buffer, n, &
H5FD_MPIO_COLLECTIVE_F)
else
call hdf5_parallel_read_string(temp_group, name, buffer, n, &
H5FD_MPIO_INDEPENDENT_F)
end if
else
! Standard read call
call hdf5_read_string(temp_group, name, buffer)
end if
# else
! Read the data serial
call hdf5_read_string(temp_group, name, buffer)
# endif
! Check if HDF5 group should be closed
if (present(group)) call hdf5_close_group()
#elif MPI
! Length of string buffer to read
n = len(buffer)
! Read the data
call mpi_read_string(mpi_fh, buffer, n)
#else

View file

@ -456,11 +456,11 @@ contains
call file_open(path_state_point, 'parallel', 'r')
! Read filetype
call read_data(int_array(1), "filetype")
call read_data(int_array(1), "filetype", option="collective")
! Read revision number for state point file and make sure it matches with
! current version
call read_data(int_array(1), "revision")
call read_data(int_array(1), "revision", option="collective")
if (int_array(1) /= REVISION_STATEPOINT) then
message = "State point version does not match current version " &
// "in OpenMC."
@ -468,9 +468,9 @@ contains
end if
! Read OpenMC version
call read_data(int_array(1), "version_major")
call read_data(int_array(2), "version_minor")
call read_data(int_array(3), "version_release")
call read_data(int_array(1), "version_major", option="collective")
call read_data(int_array(2), "version_minor", option="collective")
call read_data(int_array(3), "version_release", option="collective")
if (int_array(1) /= VERSION_MAJOR .or. int_array(2) /= VERSION_MINOR &
.or. int_array(3) /= VERSION_RELEASE) then
message = "State point file was created with a different version " &
@ -479,68 +479,70 @@ contains
end if
! Read date and time
call read_data(current_time, "date_and_time")
call read_data(current_time, "date_and_time", option="collective")
! Read path to input
call read_data(path_temp, "path")
call read_data(path_temp, "path", option="collective")
! Read and overwrite random number seed
call read_data(seed, "seed")
call read_data(seed, "seed", option="collective")
! Read and overwrite run information except number of batches
call read_data(run_mode, "run_mode")
call read_data(n_particles, "n_particles")
call read_data(int_array(1), "n_batches")
call read_data(run_mode, "run_mode", option="collective")
call read_data(n_particles, "n_particles", option="collective")
call read_data(int_array(1), "n_batches", option="collective")
! Take maximum of statepoint n_batches and input n_batches
n_batches = max(n_batches, int_array(1))
! Read batch number to restart at
call read_data(restart_batch, "current_batch")
call read_data(restart_batch, "current_batch", option="collective")
! Read information specific to eigenvalue run
if (run_mode == MODE_EIGENVALUE) then
call read_data(int_array(1), "n_inactive")
call read_data(gen_per_batch, "gen_per_batch")
call read_data(int_array(1), "n_inactive", option="collective")
call read_data(gen_per_batch, "gen_per_batch", option="collective")
call read_data(k_generation, "k_generation", &
length=restart_batch*gen_per_batch)
call read_data(entropy, "entropy", length=restart_batch*gen_per_batch)
call read_data(k_col_abs, "k_col_abs")
call read_data(k_col_tra, "k_col_tra")
call read_data(k_abs_tra, "k_abs_tra")
call read_data(real_array(1:2), "k_combined", length=2)
length=restart_batch*gen_per_batch, option="collective")
call read_data(entropy, "entropy", length=restart_batch*gen_per_batch, &
option="collective")
call read_data(k_col_abs, "k_col_abs", option="collective")
call read_data(k_col_tra, "k_col_tra", option="collective")
call read_data(k_abs_tra, "k_abs_tra", option="collective")
call read_data(real_array(1:2), "k_combined", length=2, &
option="collective")
! Take maximum of statepoint n_inactive and input n_inactive
n_inactive = max(n_inactive, int_array(1))
end if
! Read number of meshes
call read_data(n_meshes, "n_meshes", group="tallies")
call read_data(n_meshes, "n_meshes", group="tallies", option="collective")
! Read and overwrite mesh information
MESH_LOOP: do i = 1, n_meshes
call read_data(meshes(i) % id, "id", &
group="tallies/mesh" // to_str(i))
group="tallies/mesh" // to_str(i), option="collective")
call read_data(meshes(i) % type, "type", &
group="tallies/mesh" // to_str(i))
group="tallies/mesh" // to_str(i), option="collective")
call read_data(meshes(i) % n_dimension, "n_dimension", &
group="tallies/mesh" // to_str(i))
group="tallies/mesh" // to_str(i), option="collective")
call read_data(meshes(i) % dimension, "dimension", &
group="tallies/mesh" // to_str(i), &
length=meshes(i) % n_dimension)
length=meshes(i) % n_dimension, option="collective")
call read_data(meshes(i) % lower_left, "lower_left", &
group="tallies/mesh" // to_str(i), &
length=meshes(i) % n_dimension)
length=meshes(i) % n_dimension, option="collective")
call read_data(meshes(i) % upper_right, "upper_right", &
group="tallies/mesh" // to_str(i), &
length=meshes(i) % n_dimension)
length=meshes(i) % n_dimension, option="collective")
call read_data(meshes(i) % width, "width", &
group="tallies/mesh" // to_str(i), &
length=meshes(i) % n_dimension)
length=meshes(i) % n_dimension, option="collective")
end do MESH_LOOP
! Read and overwrite number of tallies
call read_data(n_tallies, "n_tallies", group="tallies")
call read_data(n_tallies, "n_tallies", group="tallies", option="collective")
! Read in tally metadata
TALLY_METADATA: do i = 1, n_tallies
@ -549,17 +551,18 @@ contains
t => tallies(i)
! Read tally id
call read_data(t % id, "id", group="tallies/tally" // to_str(i))
call read_data(t % id, "id", group="tallies/tally" // to_str(i), &
option="collective")
! Read number of realizations
call read_data(t % n_realizations, "n_realizations", &
group="tallies/tally" // to_str(i))
group="tallies/tally" // to_str(i), option="collective")
! Read size of tally results
call read_data(int_array(1), "total_score_bins", &
group="tallies/tally" // to_str(i))
group="tallies/tally" // to_str(i), option="collective")
call read_data(int_array(2), "total_filter_bins", &
group="tallies/tally" // to_str(i))
group="tallies/tally" // to_str(i), option="collective")
! Check size of tally results array
if (int_array(1) /= t % total_score_bins .and. &
@ -570,41 +573,44 @@ contains
! Read number of filters
call read_data(t % n_filters, "n_filters", &
group="tallies/tally" // to_str(i))
group="tallies/tally" // to_str(i), option="collective")
! Read filter information
FILTER_LOOP: do j = 1, t % n_filters
! Read type of filter
call read_data(t % filters(j) % type, "type", &
group="tallies/tally" // trim(to_str(i)) // "/filter" // to_str(j))
group="tallies/tally" // trim(to_str(i)) // "/filter" // to_str(j), &
option="collective")
! Read number of bins for this filter
call read_data(t % filters(j) % n_bins, "n_bins", &
group="tallies/tally" // trim(to_str(i)) // "/filter" // to_str(j))
group="tallies/tally" // trim(to_str(i)) // "/filter" // to_str(j), &
option="collective")
! Read bins
if (t % filters(j) % type == FILTER_ENERGYIN .or. &
t % filters(j) % type == FILTER_ENERGYOUT) then
call read_data(t % filters(j) % real_bins, "bins", &
group="tallies/tally" // trim(to_str(i)) // "/filter" // to_str(j), &
length=size(t % filters(j) % real_bins))
length=size(t % filters(j) % real_bins), option="collective")
else
call read_data(t % filters(j) % int_bins, "bins", &
group="tallies/tally" // trim(to_str(i)) // "/filter" // to_str(j), &
length=size(t % filters(j) % int_bins))
length=size(t % filters(j) % int_bins), option="collective")
end if
end do FILTER_LOOP
! Read number of nuclide bins
call read_data(t % n_nuclide_bins, "n_nuclide_bins", &
group="tallies/tally" // to_str(i))
group="tallies/tally" // to_str(i), option="collective")
! Set up nuclide bin array and then write
allocate(temp_array(t % n_nuclide_bins))
call read_data(temp_array, "nuclide_bins", &
group="tallies/tally" // to_str(i), length=t % n_nuclide_bins)
group="tallies/tally" // to_str(i), length=t % n_nuclide_bins, &
option="collective")
NUCLIDE_LOOP: do j = 1, t % n_nuclide_bins
if (temp_array(j) > 0) then
nuclides(t % nuclide_bins(j)) % zaid = temp_array(j)
@ -616,15 +622,17 @@ contains
! Write number of score bins, score bins, and scatt order
call read_data(t % n_score_bins, "n_score_bins", &
group="tallies/tally" // to_str(i))
group="tallies/tally" // to_str(i), option="collective")
call read_data(t % score_bins, "score_bins", &
group="tallies/tally" // to_str(i), length=t % n_score_bins)
group="tallies/tally" // to_str(i), length=t % n_score_bins, &
option="collective")
call read_data(t % scatt_order, "scatt_order", &
group="tallies/tally" // to_str(i), length=t % n_score_bins)
group="tallies/tally" // to_str(i), length=t % n_score_bins, &
option="collective")
! Write number of user score bins
call read_data(t % n_user_score_bins, "n_user_score_bins", &
group="tallies/tally" // to_str(i))
group="tallies/tally" // to_str(i), option="collective")
end do TALLY_METADATA