diff --git a/docs/img/Tracks.png b/docs/img/Tracks.png new file mode 100644 index 0000000000..39c83cd595 Binary files /dev/null and b/docs/img/Tracks.png differ diff --git a/docs/source/usersguide/input.rst b/docs/source/usersguide/input.rst index 7a61ba2b5d..68f390b66e 100644 --- a/docs/source/usersguide/input.rst +++ b/docs/source/usersguide/input.rst @@ -405,6 +405,15 @@ integers: the batch number, generation number, and particle number. *Default*: None +.. _track: + +```` Element +------------------- + +The ```` element specifies particles for which OpenMC will output binary files describing particle position at every step of its transport. This element should be followed by triplets of integers. Each triplet describes one particle. The integers in each triplet specify the batch number, generation number, and particle number, respectively. + + *Default*: None + ```` Element ------------------------ diff --git a/docs/source/usersguide/install.rst b/docs/source/usersguide/install.rst index 84f7633c2f..c05782e71d 100644 --- a/docs/source/usersguide/install.rst +++ b/docs/source/usersguide/install.rst @@ -358,6 +358,7 @@ OpenMC accepts the following command line flags: -r, --restart file Restart a previous run from a state point or a particle restart file -s, --threads N Run with *N* OpenMP threads +-t, --track Write tracks for all particles -v, --version Show version information ----------------------------------------------------- diff --git a/docs/source/usersguide/processing.rst b/docs/source/usersguide/processing.rst index 7105e9f7d1..780fe37938 100644 --- a/docs/source/usersguide/processing.rst +++ b/docs/source/usersguide/processing.rst @@ -353,9 +353,41 @@ file. Note that the data contained in the output from ``StatePoint.extract_result`` is already in a Numpy array that can be reshaped and dumped to MATLAB in one step. +---------------------------- +Particle Track Visualization +---------------------------- +.. image:: ../../img/Tracks.png + :height: 200px +OpenMC can dump particle tracks—the position of particles as they are +transported through the geometry. There are two ways to make OpenMC output +tracks: all particle tracks through a commandline argument or specific particle +tracks through settings.xml. +Running OpenMC with the argument "-t", "-track", or "--track" will cause a track +file to be created for every particle transported in the code. +The settings.xml file can dictate that specific particle tracks are output. +These particles are specified withen a ''track'' element. The ''track'' element +should contain triplets of integers specifying the batch, generation, and +particle numbers, respectively. For example, to output the tracks for particles +3 and 4 of batch 1 and generation 2 the settings.xml file should contain: +.. code-block:: xml + + 1 2 3 + 1 2 4 + + +After running OpenMC, the directory should contain a file of the form +"track_(batch #)_(generation #)_(particle #).(binary or h5)" for each particle +tracked. These track files can be converted into VTK poly data files with the +"track.py" utility. The usage of track.py is of the form "track.py [-o OUT] IN" +where OUT is the optional output filename and IN is one or more filenames +describing track files. The default output name is "track.pvtp". A common +usage of track.py is "track.py track*.binary" which will use the data from all +binary track files in the directory to write a "track.pvtp" VTK output file. +The .pvtp file can then be read and plotted by 3d visualization programs such as +Paraview. diff --git a/man/man1/openmc.1 b/man/man1/openmc.1 index fb0fdd7177..cac8d59087 100644 --- a/man/man1/openmc.1 +++ b/man/man1/openmc.1 @@ -27,6 +27,9 @@ Restart a previous run from a state point or a particle restart file named .BI \-s " N" "\fR,\fP \-\-threads" " N" Use \fIN\fP OpenMP threads. .TP +.B "\-t\fR, \fP\-\-track" +Write tracks for all particles. +.TP .B "\-v\fR, \fP\-\-version" Show version information. .TP diff --git a/src/DEPENDENCIES b/src/DEPENDENCIES index b1c339921e..b4fe997bbc 100644 --- a/src/DEPENDENCIES +++ b/src/DEPENDENCIES @@ -370,6 +370,11 @@ tally_initialize.o: tally_header.o timer_header.o: constants.o +track_output.o: global.o +track_output.o: output_interface.o +track_output.o: particle_header.o +track_output.o: string.o + tracking.o: cross_section.o tracking.o: error.o tracking.o: geometry.o @@ -381,10 +386,10 @@ tracking.o: physics.o tracking.o: random_lcg.o tracking.o: string.o tracking.o: tally.o +tracking.o: track_output.o vector_header.o: constants.o xml_interface.o: constants.o xml_interface.o: error.o xml_interface.o: global.o - diff --git a/src/global.F90 b/src/global.F90 index f12171b257..637ea315e6 100644 --- a/src/global.F90 +++ b/src/global.F90 @@ -283,6 +283,10 @@ module global 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. @@ -451,6 +455,9 @@ contains call active_tracklength_tallies % clear() call active_current_tallies % clear() call active_tallies % clear() + + ! Deallocate track_identifiers + if (allocated(track_identifiers)) deallocate(track_identifiers) ! Deallocate dictionaries call cell_dict % clear() diff --git a/src/initialize.F90 b/src/initialize.F90 index dea901fb66..b75fa20ef8 100644 --- a/src/initialize.F90 +++ b/src/initialize.F90 @@ -394,6 +394,9 @@ contains case ('-eps_tol', '-ksp_gmres_restart') ! Handle options that would be based to PETSC i = i + 1 + case ('-t', '-track', '--track') + write_all_tracks = .true. + i = i + 1 case default message = "Unknown command line option: " // argv(i) call fatal_error() diff --git a/src/input_xml.F90 b/src/input_xml.F90 index deeae3c01e..05f4ae0c56 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -56,6 +56,7 @@ contains integer :: temp_int_array3(3) integer, allocatable :: temp_int_array(:) integer(8) :: temp_long + integer :: n_tracks logical :: file_exists character(MAX_FILE_LEN) :: env_variable character(MAX_WORD_LEN) :: type @@ -459,6 +460,24 @@ contains trace_particle = int(temp_int_array3(3), 8) end if + ! Particle tracks + if (check_for_node(doc, "track")) then + ! Make sure that there are three values per particle + n_tracks = get_arraysize_integer(doc, "track") + if (mod(n_tracks, 3) /= 0) then + message = "Number of integers specified in 'track' is not divisible & + &by 3. Please provide 3 integers per particle to be tracked." + call fatal_error() + end if + + ! Allocate space and get list of tracks + allocate(temp_int_array(n_tracks)) + call get_node_array(doc, "track", temp_int_array) + + ! Reshape into track_identifiers -- note automatic array allocation + track_identifiers = reshape(temp_int_array, [3, n_tracks/3]) + end if + ! Shannon Entropy mesh if (check_for_node(doc, "entropy")) then diff --git a/src/output.F90 b/src/output.F90 index b1290f057e..c60b96bf26 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -172,6 +172,7 @@ contains write(OUTPUT_UNIT,*) ' -r, --restart Restart a previous run from a state point' write(OUTPUT_UNIT,*) ' or a particle restart file' write(OUTPUT_UNIT,*) ' -s, --threads Number of OpenMP threads' + write(OUTPUT_UNIT,*) ' -t, --track Write tracks for all particles' write(OUTPUT_UNIT,*) ' -v, --version Show version information' write(OUTPUT_UNIT,*) ' -?, --help Show this message' end if diff --git a/src/particle_header.F90 b/src/particle_header.F90 index 201de518eb..b9762960ed 100644 --- a/src/particle_header.F90 +++ b/src/particle_header.F90 @@ -76,6 +76,9 @@ module particle_header ! Statistical data integer :: n_collision ! # of collisions + ! Track output + logical :: write_track + contains procedure :: initialize => initialize_particle procedure :: clear => clear_particle diff --git a/src/relaxng/settings.rnc b/src/relaxng/settings.rnc index 82856bf97a..6af6754405 100644 --- a/src/relaxng/settings.rnc +++ b/src/relaxng/settings.rnc @@ -105,6 +105,8 @@ element settings { element trace { list { xsd:positiveInteger+ } }? & + element track { list { xsd:positiveInteger+ } }? & + element verbosity { xsd:positiveInteger }? & element uniform_fs{ diff --git a/src/source.F90 b/src/source.F90 index 67d8ec8013..2082ad6dda 100644 --- a/src/source.F90 +++ b/src/source.F90 @@ -155,6 +155,7 @@ contains integer(8), intent(in) :: index_source integer(8) :: particle_seed ! unique index for particle + integer :: i type(Bank), pointer, save :: src => null() !$omp threadprivate(src) @@ -177,6 +178,21 @@ contains if (current_batch == trace_batch .and. current_gen == trace_gen .and. & p % id == trace_particle) trace = .true. + ! Set particle track. + p % write_track = .false. + if (write_all_tracks) then + p % write_track = .true. + else if (allocated(track_identifiers)) then + do i=1, size(track_identifiers(1,:)) + if (current_batch == track_identifiers(1,i) .and. & + ¤t_gen == track_identifiers(2,i) .and. & + &p % id == track_identifiers(3,i)) then + p % write_track = .true. + exit + end if + end do + end if + end subroutine get_source_particle !=============================================================================== diff --git a/src/track_output.F90 b/src/track_output.F90 new file mode 100644 index 0000000000..4b02dfe9a2 --- /dev/null +++ b/src/track_output.F90 @@ -0,0 +1,73 @@ +!=============================================================================== +! TRACK_OUTPUT handles output of particle tracks (the paths taken by particles +! as they are transported through the geometry). +!=============================================================================== + +module track_output + + use global + use output_interface, only: BinaryOutput + use particle_header, only: Particle + use string, only: to_str + + implicit none + + integer, private :: n_tracks ! total number of tracks + real(8), private, allocatable :: coords(:,:) ! track coordinates + +contains + +!=============================================================================== +! INITIALIZE_PARTICLE_TRACK +!=============================================================================== + + subroutine initialize_particle_track() + n_tracks = 0 + allocate(coords(1,1)) + end subroutine initialize_particle_track + +!=============================================================================== +! WRITE_PARTICLE_TRACK copies particle position to an array. +!=============================================================================== + + subroutine write_particle_track(p) + type(Particle), intent(in) :: p + + real(8), allocatable :: new_coords(:, :) + + ! Add another column to coords. + n_tracks = n_tracks + 1 + allocate(new_coords(3, n_tracks)) + new_coords(:, 1:n_tracks-1) = coords + call move_alloc(FROM=new_coords, TO=coords) + + ! Write current coordinates into the newest column. + coords(:, n_tracks) = p % coord0 % xyz + end subroutine write_particle_track + +!=============================================================================== +! FINALIZE_PARTICLE_TRACK writes the particle track array to disk. +!=============================================================================== + + subroutine finalize_particle_track(p) + type(Particle), intent(in) :: p + + character(MAX_FILE_LEN) :: fname + type(BinaryOutput) :: binout + +#ifdef HDF5 + fname = trim(path_output) // 'track_' // trim(to_str(current_batch)) & + // '_' // trim(to_str(current_gen)) // '_' // trim(to_str(p % id)) & + // '.h5' +#else + fname = trim(path_output) // 'track_' // trim(to_str(current_batch)) & + // '_' // trim(to_str(current_gen)) // '_' // trim(to_str(p % id)) & + // '.binary' +#endif + call binout % file_create(fname) + call binout % write_data(coords, 'coordinates', length=(/3, n_tracks/)) + call binout % file_close() + deallocate(coords) + end subroutine finalize_particle_track + +end module track_output diff --git a/src/tracking.F90 b/src/tracking.F90 index 04175b243f..c7ee31f0b2 100644 --- a/src/tracking.F90 +++ b/src/tracking.F90 @@ -13,6 +13,8 @@ module tracking use string, only: to_str use tally, only: score_analog_tally, score_tracklength_tally, & score_surface_current + use track_output, only: initialize_particle_track, write_particle_track, & + finalize_particle_track contains @@ -67,8 +69,16 @@ contains ! Force calculation of cross-sections by setting last energy to zero micro_xs % last_E = ZERO + ! Prepare to write out particle track. + if (p % write_track) then + call initialize_particle_track() + endif + do while (p % alive) + ! Write particle track. + if (p % write_track) call write_particle_track(p) + if (check_overlaps) call check_cell_overlap(p) ! Calculate microscopic and macroscopic cross sections -- note: if the @@ -196,6 +206,12 @@ contains end do + ! Finish particle track output. + if (p % write_track) then + call write_particle_track(p) + call finalize_particle_track(p) + endif + end subroutine transport end module tracking diff --git a/src/utils/track.py b/src/utils/track.py new file mode 100755 index 0000000000..a2dca34e14 --- /dev/null +++ b/src/utils/track.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python2 +"""Convert binary particle track to VTK poly data. + +Usage information can be obtained by running 'track.py --help': + + usage: track.py [-h] [-o OUT] IN [IN ...] + + Convert particle track file to a .pvtp file. + + positional arguments: + IN Input particle track data filename(s). + + optional arguments: + -h, --help show this help message and exit + -o OUT, --out OUT Output VTK poly data filename. + +""" + +import os +import argparse +import struct +import vtk + + +def _parse_args(): + # Create argument parser. + parser = argparse.ArgumentParser( + description='Convert particle track file to a .pvtp file.') + parser.add_argument('input', metavar='IN', type=str, nargs='+', + help='Input particle track data filename(s).') + parser.add_argument('-o', '--out', metavar='OUT', type=str, dest='out', + help='Output VTK poly data filename.') + + # Parse and return commandline arguments. + return parser.parse_args() + + +def main(): + # Parse commandline arguments. + args = _parse_args() + + # Check input file extensions. + for fname in args.input: + if not (fname.endswith('.h5') or fname.endswith('.binary')): + raise ValueError("Input file names must either end with '.h5' or" + "'.binary'.") + + # Make sure that the output filename ends with '.pvtp'. + if not args.out: + args.out = 'tracks.pvtp' + elif os.path.splitext(args.out)[1] != '.pvtp': + args.out = ''.join([args.out, '.pvtp']) + + # Import HDF library if HDF files are present + for fname in args.input: + if fname.endswith('.h5'): + import h5py + break + + # Initialize data arrays and offset. + points = vtk.vtkPoints() + cells = vtk.vtkCellArray() + point_offset = 0 + for fname in args.input: + # Write coordinate values to points array. + if fname.endswith('.binary'): + track = open(fname, 'rb').read() + coords = [struct.unpack("ddd", track[24*i : 24*(i+1)]) + for i in range(len(track)/24)] + n_points = len(coords) + for triplet in coords: + points.InsertNextPoint(triplet) + else: + coords = h5py.File(fname).get('coordinates') + n_points = coords.shape[0] + for i in range(n_points): + points.InsertNextPoint(coords[i,:]) + + # Create VTK line and assign points to line. + line = vtk.vtkPolyLine() + line.GetPointIds().SetNumberOfIds(n_points) + for i in range(n_points): + line.GetPointIds().SetId(i, point_offset+i) + + cells.InsertNextCell(line) + point_offset += n_points + data = vtk.vtkPolyData() + data.SetPoints(points) + data.SetLines(cells) + + writer = vtk.vtkXMLPPolyDataWriter() + writer.SetInput(data) + writer.SetFileName(args.out) + writer.Write() + + + +if __name__ == '__main__': + main() diff --git a/tests/test_track_output/geometry.xml b/tests/test_track_output/geometry.xml new file mode 100644 index 0000000000..f3566ab17f --- /dev/null +++ b/tests/test_track_output/geometry.xml @@ -0,0 +1,305 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 + 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 + 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 + 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 3 2 2 2 2 2 2 2 3 2 2 2 + 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 + 2 2 2 1 2 2 2 2 2 2 2 1 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 1 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 1 2 2 1 2 2 2 1 2 2 1 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 3 2 2 2 2 2 2 2 1 2 2 2 + 2 2 2 2 2 1 2 2 2 1 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + + + + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 + 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 + 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 + + + + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 + 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + + + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + + + + + + + + + + -12.2682 -12.2682 + 1.63576 1.63576 + + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + + + + + + + + + + + + + + + + + + + -85.8774 -85.8774 + 24.5364 24.5364 + + 999 999 130 140 150 999 999 + 999 220 230 240 250 260 999 + 130 320 777 222 333 360 150 + 410 240 444 111 666 240 470 + 510 520 888 555 998 560 570 + 999 620 630 240 650 660 999 + 999 999 510 740 570 999 999 + + + + + + + + diff --git a/tests/test_track_output/materials.xml b/tests/test_track_output/materials.xml new file mode 100644 index 0000000000..bbf880d960 --- /dev/null +++ b/tests/test_track_output/materials.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/test_track_output/settings.xml b/tests/test_track_output/settings.xml new file mode 100644 index 0000000000..ef74341dbb --- /dev/null +++ b/tests/test_track_output/settings.xml @@ -0,0 +1,30 @@ + + + + + + + + + + 2 + 0 + 100 + + + + + + + + + -1 -1 -1 1 1 1 + + + + + 1 1 1 + 1 1 2 + + + diff --git a/tests/test_track_output/test_track_output.py b/tests/test_track_output/test_track_output.py new file mode 100644 index 0000000000..0e7674154c --- /dev/null +++ b/tests/test_track_output/test_track_output.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python + +import os +from subprocess import Popen, STDOUT, PIPE, call +import filecmp +import glob + +from nose.plugins.skip import SkipTest + +from nose_mpi import NoseMPI + +pwd = os.path.dirname(__file__) + + +def setup(): + os.putenv('PWD', pwd) + os.chdir(pwd) + + +def test_run(): + openmc_path = pwd + '/../../src/openmc' + if int(NoseMPI.mpi_np) > 0: + proc = Popen([NoseMPI.mpi_exec, '-np', NoseMPI.mpi_np, openmc_path], + stderr=STDOUT, stdout=PIPE) + else: + proc = Popen([openmc_path], stderr=STDOUT, stdout=PIPE) + returncode = proc.wait() + print(proc.communicate()[0]) + assert returncode == 0 + + +def test_created_outputs(): + outputs = [glob.glob(''.join((pwd, '/track_1_1_1.*')))] + outputs.append(glob.glob(''.join((pwd, '/track_1_1_2.*')))) + for files in outputs: + assert len(files) == 1 + assert files[0].endswith('binary') or files[0].endswith('h5') + + +def test_outputs(): + # If vtk python module is not available, we can't run track.py so skip this + # test + try: + import vtk + except ImportError: + raise SkipTest + + call(['../../src/utils/track.py', '-o', 'poly'] + + glob.glob(''.join((pwd, '/track*')))) + poly = ''.join((pwd, '/poly.pvtp')) + assert os.path.isfile(poly) + metric = ''.join((pwd, '/true_poly.pvtp')) + compare = filecmp.cmp(poly, metric) + if not compare: + os.rename('poly.pvtp', 'error_poly.pvtp') + assert compare + + +def teardown(): + temp_files = glob.glob(''.join((pwd, '/statepoint*'))) + temp_files = temp_files + glob.glob(''.join((pwd, '/track*'))) + temp_files = temp_files + glob.glob(''.join((pwd, '/poly*'))) + for f in temp_files: + if os.path.exists(f): + os.remove(f) diff --git a/tests/test_track_output/true_poly.pvtp b/tests/test_track_output/true_poly.pvtp new file mode 100644 index 0000000000..6ded87a0ec --- /dev/null +++ b/tests/test_track_output/true_poly.pvtp @@ -0,0 +1,9 @@ + + + + + + + + +