Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
Major update aimed at improving the stability and memory usage of the…
Browse files Browse the repository at this point in the history
… code. Trying to beat down out of memory errors.
  • Loading branch information
daminton committed Jan 8, 2023
1 parent a489d70 commit a237141
Show file tree
Hide file tree
Showing 34 changed files with 1,034 additions and 841 deletions.
245 changes: 185 additions & 60 deletions src/base/base_module.f90
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,11 @@ module base
logical :: lyarkovsky = .false. !! Turn on Yarkovsky effect
logical :: lyorp = .false. !! Turn on YORP effect
contains
procedure(abstract_io_dump_param), deferred :: dump
procedure(abstract_io_param_reader), deferred :: reader
procedure(abstract_io_param_writer), deferred :: writer
procedure(abstract_io_read_in_param), deferred :: read_in
procedure :: dealloc => base_util_dealloc_param
procedure(abstract_io_dump_param), deferred :: dump
procedure(abstract_io_param_reader), deferred :: reader
procedure(abstract_io_param_writer), deferred :: writer
procedure(abstract_io_read_in_param), deferred :: read_in
end type base_parameters

abstract interface
Expand Down Expand Up @@ -157,27 +158,31 @@ end subroutine abstract_io_read_in_param
type :: base_storage_frame
class(*), allocatable :: item
contains
procedure :: store => copy_store !! Stores a snapshot of the nbody system so that later it can be retrieved for saving to file.
procedure :: store => base_util_copy_store !! Stores a snapshot of the nbody system so that later it can be retrieved for saving to file.
generic :: assignment(=) => store
final :: final_storage_frame
final :: base_final_storage_frame
end type


type, abstract :: base_storage(nframes)
type, abstract :: base_storage
!! An class that establishes the pattern for various storage objects
integer(I4B), len :: nframes = 4096 !! Total number of frames that can be stored
integer(I4B) :: nframes !! Total number of frames that can be stored

!! An class that establishes the pattern for various storage objects
type(base_storage_frame), dimension(nframes) :: frame !! Array of stored frames
integer(I4B) :: iframe = 0 !! Index of the last frame stored in the system
integer(I4B) :: nid !! Number of unique id values in all saved snapshots
integer(I4B), dimension(:), allocatable :: idvals !! The set of unique id values contained in the snapshots
integer(I4B), dimension(:), allocatable :: idmap !! The id value -> index map
integer(I4B) :: nt !! Number of unique time values in all saved snapshots
real(DP), dimension(:), allocatable :: tvals !! The set of unique time values contained in the snapshots
integer(I4B), dimension(:), allocatable :: tmap !! The t value -> index map
type(base_storage_frame), dimension(:), allocatable :: frame !! Array of stored frames
integer(I4B) :: iframe = 0 !! Index of the last frame stored in the system
integer(I4B) :: nid !! Number of unique id values in all saved snapshots
integer(I4B), dimension(:), allocatable :: idvals !! The set of unique id values contained in the snapshots
integer(I4B), dimension(:), allocatable :: idmap !! The id value -> index map
integer(I4B) :: nt !! Number of unique time values in all saved snapshots
real(DP), dimension(:), allocatable :: tvals !! The set of unique time values contained in the snapshots
integer(I4B), dimension(:), allocatable :: tmap !! The t value -> index map
contains
procedure :: reset => reset_storage !! Resets a storage object by deallocating all items and resetting the frame counter to 0
procedure :: dealloc => base_util_dealloc_storage !! Deallocates all allocatables
procedure :: reset => base_util_reset_storage !! Resets the storage object back to its original state by removing all of the saved items from the storage frames
procedure :: resize => base_util_resize_storage !! Resizes storage if it is too small
procedure :: setup => base_util_setup_storage !! Sets up a storage system with a set number of frames
procedure :: save => base_util_snapshot_save !! Takes a snapshot of the current system
end type base_storage


Expand All @@ -189,8 +194,18 @@ end subroutine abstract_io_read_in_param

!> An abstract class for a generic collection of Swiftest bodies
type, abstract :: base_object
contains
procedure(abstract_util_dealloc_object), deferred :: dealloc
end type base_object

abstract interface
subroutine abstract_util_dealloc_object(self)
import base_object
implicit none
class(base_object), intent(inout) :: self !! Generic Swiftest object type
end subroutine abstract_util_dealloc_object
end interface


type, abstract :: base_multibody(nbody)
integer(I4B), len :: nbody
Expand All @@ -209,7 +224,7 @@ end subroutine abstract_io_read_in_param

contains

subroutine copy_store(self, source)
subroutine base_util_copy_store(self, source)
!! author: David A. Minton
!!
!! Stores a snapshot of the nbody system so that later it can be retrieved for saving to file.
Expand All @@ -221,70 +236,49 @@ subroutine copy_store(self, source)
allocate(self%item, source=source)

return
end subroutine copy_store
end subroutine base_util_copy_store


subroutine final_storage_frame(self)
subroutine base_util_dealloc_param(self)
!! author: David A. Minton
!!
!! Finalizer for the storage frame data type
implicit none
type(base_storage_frame) :: self

if (allocated(self%item)) deallocate(self%item)

return
end subroutine final_storage_frame


subroutine base_final_storage(self)
!! author: David A. Minton
!!
!! Finalizer for the storage object
!! Deallocates all allocatables
implicit none
! Arguments
class(base_storage(*)), intent(inout) :: self
! Internals
integer(I4B) :: i
class(base_parameters),intent(inout) :: self !! Collection of parameters

if (allocated(self%integrator)) deallocate(self%integrator)
if (allocated(self%param_file_name)) deallocate(self%param_file_name)
if (allocated(self%display_style)) deallocate(self%display_style)
if (allocated(self%seed)) deallocate(self%seed)

do i = 1, self%nframes
call final_storage_frame(self%frame(i))
end do
return
end subroutine base_final_storage
end subroutine base_util_dealloc_param


subroutine reset_storage(self)
subroutine base_util_dealloc_storage(self)
!! author: David A. Minton
!!
!! Resets a storage object by deallocating all items and resetting the frame counter to 0
implicit none
! Arguments
class(base_storage(*)), intent(inout) :: self !! Swiftest storage object
! Internals
integer(I4B) :: i

do i = 1, self%nframes
if (allocated(self%frame(i)%item)) deallocate(self%frame(i)%item)
end do

if (allocated(self%idmap)) deallocate(self%idmap)
if (allocated(self%tmap)) deallocate(self%tmap)
self%nid = 0
self%nt = 0
self%iframe = 0
class(base_storage), intent(inout) :: self !! Swiftest storage object

call self%reset()
if (allocated(self%frame)) deallocate(self%frame)
self%nframes = 0

return
end subroutine reset_storage
end subroutine base_util_dealloc_storage


subroutine util_exit(code)
subroutine base_util_exit(code)
!! author: David A. Minton
!!
!! Print termination message and exit program
!!
!! Adapted from David E. Kaufmann's Swifter routine: util_exit.f90
!! Adapted from Hal Levison's Swift routine util_exit.f
!! Adapted from David E. Kaufmann's Swifter routine: base_util_exit.f90
!! Adapted from Hal Levison's Swift routine base_util_exit.f
implicit none
! Arguments
integer(I4B), intent(in) :: code
Expand All @@ -311,6 +305,137 @@ subroutine util_exit(code)

stop

end subroutine util_exit
end subroutine base_util_exit


subroutine base_util_reset_storage(self)
!! author: David A. Minton
!!
!! Resets the storage object back to its original state by removing all of the saved items from the storage frames, but does not deallocate the frames
implicit none
! Arguments
class(base_storage), intent(inout) :: self
! Internals
integer(I4B) :: i

if (allocated(self%frame)) then
do i = 1, self%nframes
if (allocated(self%frame(i)%item)) deallocate(self%frame(i)%item)
end do
end if

if (allocated(self%idmap)) deallocate(self%idmap)
if (allocated(self%idvals)) deallocate(self%idvals)
if (allocated(self%tmap)) deallocate(self%tmap)
if (allocated(self%tvals)) deallocate(self%tvals)
self%nid = 0
self%nt = 0
self%iframe = 0

return
end subroutine base_util_reset_storage


subroutine base_util_resize_storage(self, nnew)
!! author: David A. Minton
!!
!! Checks the current size of a Swiftest against the requested size and resizes it if it is too small.
implicit none
! Arguments
class(base_storage), intent(inout) :: self !! Storage object
integer(I4B), intent(in) :: nnew !! New size
! Internals
class(base_storage_frame), dimension(:), allocatable :: tmp
integer(I4B) :: i, n, nold, nbig

nold = self%nframes
if (nnew <= nold) return

nbig = nold
do while (nbig < nnew)
nbig = nbig * 2
end do
call move_alloc(self%frame, tmp)
allocate(self%frame(nbig))
self%nframes = nbig
do i = 1, nold
if (allocated(tmp(i)%item)) call move_alloc(tmp(i)%item, self%frame(i)%item)
end do

return
end subroutine base_util_resize_storage


subroutine base_util_setup_storage(self, n)
!! author: David A. Minton
!!
!! Checks the current size of a Swiftest against the requested size and resizes it if it is too small.
implicit none
! Arguments
class(base_storage), intent(inout) :: self !! Storage object
integer(I4B), intent(in) :: n !! New size

if (allocated(self%frame)) deallocate(self%frame)
allocate(self%frame(n))
self%nframes = n

return
end subroutine base_util_setup_storage


subroutine base_util_snapshot_save(self, snapshot)
!! author: David A. Minton
!!
!! Checks the current size of the storage object against the required size and extends it by a factor of 2 more than requested if it is too small.
!! Note: The reason to extend it by a factor of 2 is for performance. When there are many enounters per step, resizing every time you want to add an
!! encounter takes significant computational effort. Resizing by a factor of 2 is a tradeoff between performance (fewer resize calls) and memory managment
!! Memory usage grows by a factor of 2 each time it fills up, but no more.
implicit none
! Arguments
class(base_storage), intent(inout) :: self !! Storage ncounter storage object
class(*), intent(in) :: snapshot !! Object to snapshot
! Internals
integer(I4B) :: nnew, nold

! Advance the snapshot frame counter
self%iframe = self%iframe + 1

nnew = self%iframe
nold = self%nframes

! Check to make sure the current storage object is big enough. If not, grow it by a factor of 2
if (nnew > nold) call self%resize(nnew)

self%frame(nnew) = snapshot

return
end subroutine base_util_snapshot_save


subroutine base_final_storage(self)
!! author: David A. Minton
!!
!! Finalizer for the storage object
implicit none
! Arguments
class(base_storage), intent(inout) :: self

call self%dealloc()
return
end subroutine base_final_storage


subroutine base_final_storage_frame(self)
!! author: David A. Minton
!!
!! Finalizer for the storage frame data type
implicit none
type(base_storage_frame) :: self

if (allocated(self%item)) deallocate(self%item)

return
end subroutine base_final_storage_frame


end module base
2 changes: 1 addition & 1 deletion src/collision/collision_generate.f90
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ module subroutine collision_generate_bounce(self, nbody_system, param, t)
call self%merge(nbody_system, param, t) ! Use the default collision model, which is merge
case default
call swiftest_io_log_one_message(COLLISION_LOG_OUT,"Error in swiftest_collision, unrecognized collision regime")
call util_exit(FAILURE)
call base_util_exit(FAILURE)
end select
end associate
end select
Expand Down
6 changes: 3 additions & 3 deletions src/collision/collision_io.f90
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ module subroutine collision_io_netcdf_dump(self, param)
!! Dumps the time history of an encounter to file.
implicit none
! Arguments
class(collision_storage(*)), intent(inout) :: self !! Encounter storage object
class(collision_storage), intent(inout) :: self !! Encounter storage object
class(base_parameters), intent(inout) :: param !! Current run configuration parameters
! Internals
integer(I4B) :: i
Expand Down Expand Up @@ -266,7 +266,7 @@ module subroutine collision_io_netcdf_initialize_output(self, param)

667 continue
write(*,*) "Error creating fragmentation output file. " // trim(adjustl(errmsg))
call util_exit(FAILURE)
call base_util_exit(FAILURE)
end subroutine collision_io_netcdf_initialize_output


Expand Down Expand Up @@ -359,7 +359,7 @@ module subroutine collision_io_netcdf_write_frame_snapshot(self, history, param)
implicit none
! Arguments
class(collision_snapshot), intent(in) :: self !! Swiftest encounter structure
class(encounter_storage(*)), intent(inout) :: history !! Collision history object
class(encounter_storage), intent(inout) :: history !! Collision history object
class(base_parameters), intent(inout) :: param !! Current run configuration parameters
! Internals
integer(I4B) :: i, idslot, old_mode, npl, stage
Expand Down
Loading

0 comments on commit a237141

Please sign in to comment.