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

Commit

Permalink
Merge branch 'Simulation_API_improvements' into debug
Browse files Browse the repository at this point in the history
  • Loading branch information
daminton committed Nov 23, 2022
2 parents 80e6d97 + 92702fc commit b058169
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 86 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ SET(SWIFTEST_DRIVER swiftest_driver)
SET(SRC ${CMAKE_SOURCE_DIR}/src)
SET(LIB ${CMAKE_SOURCE_DIR}/lib)
SET(BIN ${CMAKE_SOURCE_DIR}/bin)
SET(MOD ${CMAKE_SOURCE_DIR}/include)

# Have the .mod files placed in the lib folder
SET(CMAKE_Fortran_MODULE_DIRECTORY ${LIB})
SET(CMAKE_Fortran_MODULE_DIRECTORY ${MOD})

# The source for the SWIFTEST binary and have it placed in the bin folder
ADD_SUBDIRECTORY(${SRC} ${BIN})
Expand Down
4 changes: 3 additions & 1 deletion examples/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
*/param.*
*/.swiftest*
*/simdata/*
*/*/simdata/*

37 changes: 0 additions & 37 deletions examples/Basic_Simulation/simdata/param.in

This file was deleted.

43 changes: 36 additions & 7 deletions python/swiftest/swiftest/simulation_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import subprocess
import shlex
import warnings
from tqdm.auto import tqdm
from typing import (
Literal,
Dict,
Expand Down Expand Up @@ -365,23 +366,50 @@ def _run_swiftest_driver(self):
f.write(f"#{self._shell_full} -l\n")
f.write(f"source ~/.{self._shell}rc\n")
f.write(f"cd {self.sim_dir}\n")
f.write(f"{str(self.driver_executable)} {self.integrator} {str(self.param_file)} progress\n")
f.write(f"{str(self.driver_executable)} {self.integrator} {str(self.param_file)} compact\n")

cmd = f"{env['SHELL']} -l {driver_script}"

def _type_scrub(output_data):
int_vars = ["ILOOP","NPL","NTP","NPLM"]
for k,v in output_data.items():
if k in int_vars:
output_data[k] = int(v)
else:
output_data[k] = float(v)
return output_data

try:
with subprocess.Popen(shlex.split(cmd),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env=env,
universal_newlines=True) as p:
process_output = False
noutput = int((self.param['TSTOP'] - self.param['T0']) / self.param['DT'])
iloop = int((self.param['TSTART'] - self.param['T0']) / self.param['DT'])
pbar = tqdm(total=noutput)
for line in p.stdout:
if '[' in line:
print(line.replace('\n', '\r'), end='')
elif "Normal termination" in line:
print(line.replace("Normal termination", "\n\nNormal termination"), end='')
else:
print(line, end='')
if "SWIFTEST STOP" in line:
process_output = False

if process_output:
kvstream=line.replace('\n','').strip().split(';') # Removes the newline character,
output_data = _type_scrub({kv.split()[0]: kv.split()[1] for kv in kvstream[:-1]})
pre_message = f"Time: {output_data['T']} / {self.param['TSTOP']} {self.TU_name}"
post_message = f"npl: {output_data['NPL']} ntp: {output_data['NTP']}"
if "NPLM" in output_data:
post_message = post_message + f" nplm: {output_data['NPLM']}"
pbar.set_description_str(pre_message)
pbar.set_postfix_str(post_message)
interval = output_data['ILOOP'] - iloop
if interval > 0:
pbar.update(interval)
iloop = output_data['ILOOP']

if "SWIFTEST START" in line:
process_output = True

res = p.communicate()
if p.returncode != 0:
for line in res[1]:
Expand All @@ -390,6 +418,7 @@ def _run_swiftest_driver(self):
except:
warnings.warn(f"Error executing main swiftest_driver program", stacklevel=2)

pbar.close()
return

def run(self,**kwargs):
Expand Down
100 changes: 80 additions & 20 deletions src/io/io.f90
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,95 @@ module subroutine io_compact_output(self, param, timer)
!! Generates the terminal output displayed when display_style is set to COMPACT. This is used by the Python driver to
!! make nice-looking progress reports.
implicit none

interface fmt
!! author: David Minton
!!
!! Formats a pair of variables and corresponding values for the compact display output. Generic interface for different variable types to format.
procedure :: fmt_I4B, fmt_I8B, fmt_DP
end interface

! Arguments
class(swiftest_nbody_system), intent(in) :: self !! Swiftest nbody system object
class(swiftest_parameters), intent(in) :: param !! Input colleciton of user-defined parameters
class(*), intent(in) :: timer !! Object used for computing elapsed wall time (must be unlimited polymorphic because the walltimer module requires swiftest_classes)
! Internals
character(*), parameter :: COMPACTFMT = '("ILOOP",I,";T",ES23.16,";WT",ES23.16,";IWT",ES23.16,";WTPS",ES23.16,";NPL",I,";NTP",I,";"$)'
character(*), parameter :: SYMBAFMT = '(";NPLM",I,$)'
character(*), parameter :: EGYFMT = '("LTOTERR",ES24.16,";ETOTERR",ES24.16,";MTOTERR",ES24.16,";KEOERR",ES24.16,";KESERR",ES24.16,";PEERR",ES24.16' &
// '";EORBERR",ES24.16,";ECOLERR",ES24.16,";EUNTRERR",ES24.16,";LSPINERR",ES24.16,";LESCERR",ES24.16' &
// '";MESCERR",ES24.16,$)'
character(len=:), allocatable :: formatted_output

select type(timer)
class is (walltimer)
if (.not. timer%main_is_started) then ! This is the start of a new run
write(*,*) "START"
write(*,COMPACTFMT) 0,param%t,0.0,0.0,0.0,self%pl%nbody, self%tp%nbody
else
write(*,COMPACTFMT) param%iloop,param%t, timer%wall_main, timer%wall_step, timer%wall_per_substep,self%pl%nbody, self%tp%nbody
end if
formatted_output = fmt("ILOOP",param%iloop) // fmt("T",param%t) // fmt("NPL",self%pl%nbody) // fmt("NTP",self%tp%nbody)
select type(pl => self%pl)
class is (symba_pl)
write(*,SYMBAFMT) pl%nplm
formatted_output = formatted_output // fmt("NPLM",pl%nplm)
end select
if (param%lenergy) then
write(*,EGYFMT) self%Ltot_error, self%Etot_error, self%Mtot_error, self%ke_orbit_error, self%ke_spin_error, self%pe_error, &
self%Eorbit_error, self%Ecoll_error, self%Euntracked_error, self%Lspin_error, self%Lescape_error, self%Mescape_error
formatted_output = formatted_output // fmt("LTOTERR",self%Ltot_error) // fmt("ETOTERR",self%Mtot_error) // fmt("MTOTERR",self%Mtot_error) &
// fmt("KEOERR",self%ke_orbit_error) // fmt("PEERR",self%pe_error) // fmt("EORBERR",self%Eorbit_error) &
// fmt("EUNTRERR",self%Euntracked_error) // fmt("LESCERR",self%Lescape_error) // fmt("MESCERR",self%Mescape_error)
if (param%lclose) formatted_output = formatted_output // fmt("ECOLLERR",self%Ecoll_error)
if (param%lrotation) formatted_output = formatted_output // fmt("KESPINERR",self%ke_spin_error) // fmt("LSPINERR",self%Lspin_error)
end if

if (.not. timer%main_is_started) then ! This is the start of a new run
formatted_output = formatted_output // fmt("WT",0.0_DP) // fmt("IWT",0.0_DP) // fmt("WTPS",0.0_DP)
else
formatted_output = formatted_output // fmt("WT",timer%wall_main) // fmt("IWT",timer%wall_step) // fmt("WTPS",timer%wall_per_substep)
end if
write(*,*)
write(*,*) formatted_output
end select
return

contains

function fmt_I4B(varname,val) result(pair_string)
implicit none
! Arguments
character(*), intent(in) :: varname !! The variable name of the pair
integer(I4B), intent(in) :: val !! A 4-byte integer value
! Result
character(len=:), allocatable :: pair_string
! Internals
character(len=24) :: str_value

write(str_value,*) val
pair_string = trim(adjustl(varname)) // " " // trim(adjustl(str_value)) // ";"

return
end function fmt_I4B

function fmt_I8B(varname, val) result(pair_string)
implicit none
! Arguments
character(*), intent(in) :: varname !! The variable name of the pair
integer(I8B), intent(in) :: val !! An 8-byte integer value
! Result
character(len=:), allocatable :: pair_string
! Internals
character(len=24) :: str_value

write(str_value,*) val
pair_string = trim(adjustl(varname)) // " " // trim(adjustl(str_value)) // ";"

return
end function fmt_I8B

function fmt_DP(varname, val) result(pair_string)
implicit none
! Arguments
character(*), intent(in) :: varname !! The variable name of the pair
real(DP), intent(in) :: val !! A double precision floating point value
! Result
character(len=:), allocatable :: pair_string
! Internals
character(len=24) :: str_value

write(str_value,'(ES24.16)') val
pair_string = trim(adjustl(varname)) // " " // trim(adjustl(str_value)) // ";"

return
end function fmt_DP

end subroutine io_compact_output


Expand Down Expand Up @@ -115,7 +175,7 @@ module subroutine io_conservation_report(self, param, lterminal)
system%Mescape_error = system%GMescape / system%GMtot_orig
system%Mtot_error = (GMtot_now - system%GMtot_orig) / system%GMtot_orig
if (lterminal) write(display_unit, EGYTERMFMT) system%Ltot_error, system%Ecoll_error, system%Etot_error,system%Mtot_error
if (abs(Merror) > 100 * epsilon(Merror)) then
if (abs(system%Mtot_error) > 100 * epsilon(system%Mtot_error)) then
write(*,*) "Severe error! Mass not conserved! Halting!"
! Save the frame of data to the bin file in the slot just after the present one for diagnostics
param%ioutput = param%ioutput + 1_I8B
Expand Down Expand Up @@ -379,9 +439,9 @@ module subroutine io_get_args(integrator, param_file_name, display_style)
!! Reads in the name of the parameter file from command line arguments.
implicit none
! Arguments
integer(I4B) :: integrator !! Symbolic code of the requested integrator
character(len=:), allocatable :: param_file_name !! Name of the input parameters file
character(len=:), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD"
character(len=:), intent(inout), allocatable :: integrator !! Symbolic code of the requested integrator
character(len=:), intent(inout), allocatable :: param_file_name !! Name of the input parameters file
character(len=:), intent(inout), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD"
! Internals
character(len=STRMAX), dimension(:), allocatable :: arg
integer(I4B), dimension(:), allocatable :: ierr
Expand Down Expand Up @@ -599,7 +659,7 @@ module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg)
integer, intent(in) :: unit !! File unit number
character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT.
!! If you do not include a char-literal-constant, the iotype argument contains only DT.
integer, intent(in) :: v_list(:) !! The first element passes the integrator code to the reader
character(len=*), intent(in) :: v_list(:) !! The first element passes the integrator code to the reader
integer, intent(out) :: iostat !! IO status code
character(len=*), intent(inout) :: iomsg !! Message to pass if iostat /= 0
! Internals
Expand Down
12 changes: 8 additions & 4 deletions src/main/swiftest_driver.f90
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ program swiftest_driver

class(swiftest_nbody_system), allocatable :: nbody_system !! Polymorphic object containing the nbody system to be integrated
class(swiftest_parameters), allocatable :: param !! Run configuration parameters
integer(I4B) :: integrator !! Integrator type code (see swiftest_globals for symbolic names)
character(len=:), allocatable :: integrator !! Integrator type code (see swiftest_globals for symbolic names)
character(len=:),allocatable :: param_file_name !! Name of the file containing user-defined parameters
character(len=:), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD"
integer(I4B) :: ierr !! I/O error code
Expand Down Expand Up @@ -102,6 +102,7 @@ program swiftest_driver
write(pbarmessage,fmt=pbarfmt) t0, tstop
call pbar%update(1,message=pbarmessage)
else if (display_style == "COMPACT") then
write(*,*) "SWIFTEST START " // trim(adjustl(param%integrator))
call nbody_system%compact_output(param,integration_timer)
end if
do iloop = 1, nloops
Expand All @@ -121,7 +122,7 @@ program swiftest_driver
iout = iout - 1
if (iout == 0) then
ioutput = ioutput_t0 + iloop / istep_out
if (t > old_t_final) call nbody_system%write_frame(param)
call nbody_system%write_frame(param)

tfrac = (param%t - param%t0) / (param%tstop - param%t0)

Expand All @@ -133,15 +134,17 @@ program swiftest_driver
end select
if (param%lenergy) call nbody_system%conservation_report(param, lterminal=.true.)
call integration_timer%report(message="Integration steps:", unit=display_unit, nsubsteps=istep_out)
call integration_timer%reset()

iout = istep_out
if (display_style == "PROGRESS") then
write(pbarmessage,fmt=pbarfmt) t, tstop
call pbar%update(1,message=pbarmessage)
else if (display_style == "COMPACT") then
call nbody_system%compact_output(param,integration_timer)
end if

call integration_timer%reset()

iout = istep_out
end if
end if

Expand All @@ -154,6 +157,7 @@ program swiftest_driver
end if
end if
end do
if (display_style == "COMPACT") write(*,*) "SWIFTEST STOP" // trim(adjustl(param%integrator))
end associate

call nbody_system%dealloc()
Expand Down
10 changes: 5 additions & 5 deletions src/modules/swiftest_classes.f90
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module swiftest_classes
!> User defined parameters that are read in from the parameters input file.
!> Each paramter is initialized to a default values.
type :: swiftest_parameters
integer(I4B) :: integrator = UNKNOWN_INTEGRATOR !! Symbolic name of the nbody integrator used
character(STRMAX) :: integrator = UNKNOWN_INTEGRATOR !! Symbolic name of the nbody integrator used
character(STRMAX) :: param_file_name = "param.in" !! The default name of the parameter input file
integer(I4B) :: maxid = -1 !! The current maximum particle id number
integer(I4B) :: maxid_collision = 0 !! The current maximum collision id number
Expand Down Expand Up @@ -657,9 +657,9 @@ end subroutine io_dump_system

module subroutine io_get_args(integrator, param_file_name, display_style)
implicit none
integer(I4B) :: integrator !! Symbolic code of the requested integrator
character(len=:), allocatable :: param_file_name !! Name of the input parameters file
character(len=:), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT"}). Default is "STANDARD"
character(len=:), allocatable, intent(inout) :: integrator !! Symbolic code of the requested integrator
character(len=:), allocatable, intent(inout) :: param_file_name !! Name of the input parameters file
character(len=:), allocatable, intent(inout) :: display_style !! Style of the output display {"STANDARD", "COMPACT"}). Default is "STANDARD"
end subroutine io_get_args

module function io_get_old_t_final_system(self, param) result(old_t_final)
Expand Down Expand Up @@ -697,7 +697,7 @@ module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg)
integer(I4B), intent(in) :: unit !! File unit number
character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT.
!! If you do not include a char-literal-constant, the iotype argument contains only DT.
integer(I4B), intent(in) :: v_list(:) !! The first element passes the integrator code to the reader
character(len=*), intent(in) :: v_list(:) !! The first element passes the integrator code to the reader
integer(I4B), intent(out) :: iostat !! IO status code
character(len=*), intent(inout) :: iomsg !! Message to pass if iostat /= 0
end subroutine io_param_reader
Expand Down
18 changes: 9 additions & 9 deletions src/modules/swiftest_globals.f90
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,15 @@ module swiftest_globals
real(SP), parameter :: VERSION_NUMBER = 1.0_SP !! swiftest version

!> Symbolic name for integrator types
integer(I4B), parameter :: UNKNOWN_INTEGRATOR = 1
integer(I4B), parameter :: BS = 2
integer(I4B), parameter :: HELIO = 3
integer(I4B), parameter :: RA15 = 4
integer(I4B), parameter :: TU4 = 5
integer(I4B), parameter :: WHM = 6
integer(I4B), parameter :: RMVS = 7
integer(I4B), parameter :: SYMBA = 8
integer(I4B), parameter :: RINGMOONS = 9
character(*), parameter :: UNKNOWN_INTEGRATOR = "UKNOWN INTEGRATOR"
character(*), parameter :: BS = "Bulirsch-Stoer"
character(*), parameter :: HELIO = "Democratic Heliocentric"
character(*), parameter :: RA15 = "Radau 15th order"
character(*), parameter :: TU4 = "T+U 4th order"
character(*), parameter :: WHM = "Wisdom-Holman Method"
character(*), parameter :: RMVS = "Regularized Mixed Variable Symplectic"
character(*), parameter :: SYMBA = "SyMBA"
character(*), parameter :: RINGMOONS = "SyMBA-RINGMOONS"

integer(I4B), parameter :: STRMAX = 512 !! Maximum size of character strings
integer(I4B), parameter :: NAMELEN = 32 !! Maximum size of name strings
Expand Down
Loading

0 comments on commit b058169

Please sign in to comment.