diff --git a/examples/Basic_Simulation/initial_conditions.ipynb b/examples/Basic_Simulation/initial_conditions.ipynb index 2014b6e06..2bcd9cfe7 100644 --- a/examples/Basic_Simulation/initial_conditions.ipynb +++ b/examples/Basic_Simulation/initial_conditions.ipynb @@ -2,18 +2,10 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "2c4f59ea-1251-49f6-af1e-5695d7e25500", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "env: OMP_NUM_THREADS=4\n" - ] - } - ], + "outputs": [], "source": [ "import swiftest\n", "import numpy as np\n", @@ -23,7 +15,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "6054c7ab-c748-4b39-9fee-d8b27326f497", "metadata": {}, "outputs": [], @@ -34,459 +26,10 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "1c122676-bacb-447c-bc37-5ef8019be0d0", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Creating the Sun as a central body\n", - "Fetching ephemerides data for Mercury from JPL/Horizons\n", - "Fetching ephemerides data for Venus from JPL/Horizons\n", - "Fetching ephemerides data for Earth from JPL/Horizons\n", - "Fetching ephemerides data for Mars from JPL/Horizons\n", - "Fetching ephemerides data for Jupiter from JPL/Horizons\n", - "Fetching ephemerides data for Saturn from JPL/Horizons\n", - "Fetching ephemerides data for Uranus from JPL/Horizons\n", - "Fetching ephemerides data for Neptune from JPL/Horizons\n", - "Fetching ephemerides data for Pluto from JPL/Horizons\n", - "Writing initial conditions to file /home/daminton/git_debug/swiftest/examples/Basic_Simulation/.swiftest/init_cond.nc\n", - "Writing parameter inputs to file /home/daminton/git_debug/swiftest/examples/Basic_Simulation/.swiftest/param.in\n" - ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
<xarray.Dataset>\n",
-       "Dimensions:        (name: 10, time: 1)\n",
-       "Coordinates:\n",
-       "  * name           (name) <U32 'Sun' 'Mercury' 'Venus' ... 'Neptune' 'Pluto'\n",
-       "  * time           (time) float64 0.0\n",
-       "Data variables: (12/20)\n",
-       "    particle_type  (name) <U32 'Central Body' 'Massive Body' ... 'Massive Body'\n",
-       "    id             (name) int64 0 1 2 3 4 5 6 7 8 9\n",
-       "    a              (time, name) float64 nan 0.3871 0.7233 ... 19.24 30.04 39.37\n",
-       "    e              (time, name) float64 nan 0.2056 0.006718 ... 0.008956 0.2487\n",
-       "    inc            (time, name) float64 nan 7.003 3.394 ... 0.773 1.771 17.17\n",
-       "    capom          (time, name) float64 nan 48.3 76.6 ... 74.01 131.8 110.3\n",
-       "    ...             ...\n",
-       "    roty           (time, name) float64 -38.76 -18.38 ... -2.177e+03 261.3\n",
-       "    rotz           (time, name) float64 82.25 34.36 8.703 ... 2.33e+03 -38.57\n",
-       "    j2rp2          (time, name) float64 4.754e-12 nan nan nan ... nan nan nan\n",
-       "    j4rp4          (time, name) float64 -2.247e-18 nan nan nan ... nan nan nan\n",
-       "    ntp            (time) int64 0\n",
-       "    npl            (time) int64 9
" - ], - "text/plain": [ - "\n", - "Dimensions: (name: 10, time: 1)\n", - "Coordinates:\n", - " * name (name) \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
<xarray.Dataset>\n",
-       "Dimensions:        (name: 5, time: 1)\n",
-       "Coordinates:\n",
-       "  * name           (name) <U14 'MassiveBody_01' ... 'MassiveBody_05'\n",
-       "  * time           (time) float64 0.0\n",
-       "Data variables: (12/18)\n",
-       "    particle_type  (name) <U14 'Massive Body' 'Massive Body' ... 'Massive Body'\n",
-       "    id             (name) int64 10 11 12 13 14\n",
-       "    a              (time, name) float64 0.833 0.5434 0.799 0.3786 1.063\n",
-       "    e              (time, name) float64 0.2656 0.1473 0.178 0.1331 0.2989\n",
-       "    inc            (time, name) float64 82.77 64.86 84.68 52.85 16.77\n",
-       "    capom          (time, name) float64 230.6 328.9 222.6 269.3 218.2\n",
-       "    ...             ...\n",
-       "    Ip3            (time, name) float64 0.4 0.4 0.4 0.4 0.4\n",
-       "    rotx           (time, name) float64 0.0 0.0 0.0 0.0 0.0\n",
-       "    roty           (time, name) float64 0.0 0.0 0.0 0.0 0.0\n",
-       "    rotz           (time, name) float64 0.0 0.0 0.0 0.0 0.0\n",
-       "    ntp            (time) int64 0\n",
-       "    npl            (time) int64 4
" - ], - "text/plain": [ - "\n", - "Dimensions: (name: 5, time: 1)\n", - "Coordinates:\n", - " * name (name) \n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
<xarray.Dataset>\n",
-       "Dimensions:        (name: 10, time: 1)\n",
-       "Coordinates:\n",
-       "  * name           (name) <U15 'TestParticle_01' ... 'TestParticle_10'\n",
-       "  * time           (time) float64 0.0\n",
-       "Data variables:\n",
-       "    particle_type  (name) <U15 'Test Particle' ... 'Test Particle'\n",
-       "    id             (name) int64 15 16 17 18 19 20 21 22 23 24\n",
-       "    a              (time, name) float64 1.23 0.4818 0.8926 ... 0.8866 0.9032\n",
-       "    e              (time, name) float64 0.2545 0.02039 0.107 ... 0.1635 0.1588\n",
-       "    inc            (time, name) float64 74.72 69.71 6.346 ... 14.14 65.34 44.03\n",
-       "    capom          (time, name) float64 128.9 142.6 267.7 ... 311.2 62.34 253.7\n",
-       "    omega          (time, name) float64 95.45 208.0 74.89 ... 146.6 136.8 181.0\n",
-       "    capm           (time, name) float64 100.1 189.3 202.6 ... 327.8 270.4 188.0\n",
-       "    ntp            int64 10\n",
-       "    npl            int64 0
" - ], - "text/plain": [ - "\n", - "Dimensions: (name: 10, time: 1)\n", - "Coordinates:\n", - " * name (name) \u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0msim\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/git_debug/swiftest/python/swiftest/swiftest/simulation_class.py\u001b[0m in \u001b[0;36mrun\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 404\u001b[0m \u001b[0menv\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0menv\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 405\u001b[0m universal_newlines=True) as p:\n\u001b[0;32m--> 406\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mline\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstdout\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 407\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;34m'['\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mline\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 408\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreplace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'\\n'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m'\\r'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mKeyboardInterrupt\u001b[0m: " - ] - } - ], + "outputs": [], "source": [ "sim.run()" ] diff --git a/python/swiftest/swiftest/simulation_class.py b/python/swiftest/swiftest/simulation_class.py index c15da7ba9..1996b1625 100644 --- a/python/swiftest/swiftest/simulation_class.py +++ b/python/swiftest/swiftest/simulation_class.py @@ -391,10 +391,10 @@ def run(self,**kwargs): env = os.environ.copy() driver_script = os.path.join(self.binary_path,"swiftest_driver.sh") with open(driver_script,'w') as f: - f.write(f"#{self._shell_full} -l {os.linesep}") - f.write(f"source ~/.{self._shell}rc {os.linesep}") - f.write(f"cd {self.sim_dir} {os.linesep}") - f.write(f"{str(self.driver_executable)} {self.integrator} {str(self.param_file)} {os.linesep}") + 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)} compact\n") cmd = f"{env['SHELL']} -l {driver_script}" oldline = None diff --git a/src/io/io.f90 b/src/io/io.f90 index 2c74a42ee..7296d00dd 100644 --- a/src/io/io.f90 +++ b/src/io/io.f90 @@ -36,17 +36,7 @@ module subroutine io_conservation_report(self, param, lterminal) "; D(Eorbit+Ecollisions)/|E0| = ", ES12.5, & "; DM/M0 = ", ES12.5)' - associate(system => self, pl => self%pl, cb => self%cb, npl => self%pl%nbody) - if (((param%out_type == REAL4_TYPE) .or. (param%out_type == REAL8_TYPE)) .and. (param%energy_out /= "")) then - if (param%lfirstenergy .and. (param%out_stat /= "OLD")) then - open(unit=EGYIU, file=param%energy_out, form="formatted", status="replace", action="write", err=667, iomsg=errmsg) - write(EGYIU,EGYHEADER, err=667, iomsg=errmsg) - else - open(unit=EGYIU, file=param%energy_out, form="formatted", status="old", action="write", & - position="append", err=667, iomsg=errmsg) - end if - end if - + associate(system => self, pl => self%pl, cb => self%cb, npl => self%pl%nbody, display_unit => param%display_unit) call pl%vb2vh(cb) call pl%xh2xb(cb) @@ -69,34 +59,22 @@ module subroutine io_conservation_report(self, param, lterminal) param%lfirstenergy = .false. end if - if (((param%out_type == REAL4_TYPE) .or. (param%out_type == REAL8_TYPE)) .and. (param%energy_out /= "")) then - write(EGYIU,EGYFMT, err = 667, iomsg = errmsg) param%t, Eorbit_now, system%Ecollisions, Ltot_now, GMtot_now - close(EGYIU, err = 667, iomsg = errmsg) - end if - if (.not.param%lfirstenergy) then Lerror = norm2(Ltot_now(:) - system%Ltot_orig(:)) / norm2(system%Ltot_orig(:)) Eorbit_error = (Eorbit_now - system%Eorbit_orig) / abs(system%Eorbit_orig) Ecoll_error = system%Ecollisions / abs(system%Eorbit_orig) Etotal_error = (Eorbit_now - system%Ecollisions - system%Eorbit_orig - system%Euntracked) / abs(system%Eorbit_orig) Merror = (GMtot_now - system%GMtot_orig) / system%GMtot_orig - if (lterminal) write(*, EGYTERMFMT) Lerror, Ecoll_error, Etotal_error, Merror + if (lterminal) write(display_unit, EGYTERMFMT) Lerror, Ecoll_error, Etotal_error, Merror if (abs(Merror) > 100 * epsilon(Merror)) then write(*,*) "Severe error! Mass not conserved! Halting!" - if ((param%out_type == REAL4_TYPE) .or. (param%out_type == REAL8_TYPE)) then - write(*,*) "Merror = ", Merror - write(*,*) "GMtot_now : ",GMtot_now - write(*,*) "GMtot_orig: ",system%GMtot_orig - write(*,*) "Difference: ",GMtot_now - system%GMtot_orig - else if ((param%out_type == NETCDF_FLOAT_TYPE) .or. (param%out_type == NETCDF_DOUBLE_TYPE)) then - ! 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 - call pl%xv2el(cb) - call self%write_hdr(param%nciu, param) - call cb%write_frame(param%nciu, param) - call pl%write_frame(param%nciu, param) - call param%nciu%close() - end if + ! 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 + call pl%xv2el(cb) + call self%write_hdr(param%nciu, param) + call cb%write_frame(param%nciu, param) + call pl%write_frame(param%nciu, param) + call param%nciu%close() call util_exit(FAILURE) end if end if @@ -346,7 +324,7 @@ module subroutine io_dump_system(self, param) end subroutine io_dump_system - module function io_get_args(integrator, param_file_name) result(ierr) + module subroutine io_get_args(integrator, param_file_name, display_style) !! author: David A. Minton !! !! Reads in the name of the parameter file from command line arguments. @@ -354,59 +332,70 @@ module function io_get_args(integrator, param_file_name) result(ierr) ! Arguments integer(I4B) :: integrator !! Symbolic code of the requested integrator character(len=:), allocatable :: param_file_name !! Name of the input parameters file - ! Result - integer(I4B) :: ierr !! I/O error code + character(len=:), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT"}). Default is "STANDARD" ! Internals - character(len=STRMAX) :: arg1, arg2 - integer :: narg,ierr_arg1, ierr_arg2 + character(len=STRMAX), dimension(:), allocatable :: arg + integer(I4B), dimension(:), allocatable :: ierr + integer :: i,narg character(len=*),parameter :: linefmt = '(A)' - ierr = -1 ! Default is to fail - narg = command_argument_count() ! - if (narg == 2) then - call get_command_argument(1, arg1, status = ierr_arg1) - call get_command_argument(2, arg2, status = ierr_arg2) - if ((ierr_arg1 == 0) .and. (ierr_arg2 == 0)) then - ierr = 0 - call io_toupper(arg1) - select case(arg1) - case('BS') - integrator = BS - case('HELIO') - integrator = HELIO - case('RA15') - integrator = RA15 - case('TU4') - integrator = TU4 - case('WHM') - integrator = WHM - case('RMVS') - integrator = RMVS - case('SYMBA') - integrator = SYMBA - case('RINGMOONS') - integrator = RINGMOONS - case default - integrator = UNKNOWN_INTEGRATOR - write(*,*) trim(adjustl(arg1)) // ' is not a valid integrator.' - ierr = -1 - end select - param_file_name = trim(adjustl(arg2)) - end if - else - call get_command_argument(1, arg1, status = ierr_arg1) - if (ierr_arg1 == 0) then - if (arg1 == '-v' .or. arg1 == '--version') then - call util_version() - else if (arg1 == '-h' .or. arg1 == '--help') then - call util_exit(HELP) - end if + narg = command_argument_count() + if (narg > 0) then + allocate(arg(narg),ierr(narg)) + do i = 1,narg + call get_command_argument(i, arg(i), status = ierr(i)) + end do + if (any(ierr /= 0)) call util_exit(USAGE) + else + call util_exit(USAGE) + end if + + if (narg == 1) then + if (arg(1) == '-v' .or. arg(1) == '--version') then + call util_version() + else if (arg(1) == '-h' .or. arg(1) == '--help') then + call util_exit(HELP) + else + call util_exit(USAGE) end if + else if (narg >= 2) then + call io_toupper(arg(1)) + select case(arg(1)) + case('BS') + integrator = BS + case('HELIO') + integrator = HELIO + case('RA15') + integrator = RA15 + case('TU4') + integrator = TU4 + case('WHM') + integrator = WHM + case('RMVS') + integrator = RMVS + case('SYMBA') + integrator = SYMBA + case('RINGMOONS') + integrator = RINGMOONS + case default + integrator = UNKNOWN_INTEGRATOR + write(*,*) trim(adjustl(arg(1))) // ' is not a valid integrator.' + call util_exit(USAGE) + end select + param_file_name = trim(adjustl(arg(2))) + end if + + if (narg == 2) then + display_style = "STANDARD" + else if (narg == 3) then + call io_toupper(arg(3)) + display_style = trim(adjustl(arg(3))) + else + call util_exit(USAGE) end if - if (ierr /= 0) call util_exit(USAGE) return - end function io_get_args + end subroutine io_get_args module function io_get_old_t_final_system(self, param) result(old_t_final) @@ -555,7 +544,6 @@ module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg) !! !! Adapted from David E. Kaufmann's Swifter routine io_init_param.f90 !! Adapted from Martin Duncan's Swift routine io_init_param.f - use, intrinsic :: iso_fortran_env implicit none ! Arguments class(swiftest_parameters), intent(inout) :: self !! Collection of parameters @@ -940,7 +928,7 @@ module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg) iostat = 0 ! Print the contents of the parameter file to standard output - ! call param%writer(unit = OUTPUT_UNIT, iotype = "none", v_list = [0], iostat = iostat, iomsg = iomsg) + call param%writer(unit = param%display_unit, iotype = "none", v_list = [0], iostat = iostat, iomsg = iomsg) end associate @@ -1801,7 +1789,6 @@ module subroutine io_read_in_param(self, param_file_name) ! Read in name of parameter file write(*, *) 'Parameter input file is ', trim(adjustl(param_file_name)) - write(*, *) ' ' self%param_file_name = param_file_name !! todo: Currently this procedure does not work in user-defined derived-type input mode @@ -1913,6 +1900,41 @@ module subroutine io_read_particle_info_system(self, param) end subroutine io_read_particle_info_system + module subroutine io_set_display_param(self, display_style) + !! author: David A. Minton + !! + !! Sets the display style parameters. If display is "STANDARD" then output goes to stdout. If display is "COMPACT" + !! then it is redirected to a log file and a progress-bar is used for stdout + implicit none + ! Arguments + class(swiftest_parameters), intent(inout) :: self !! Current run configuration parameters + character(*), intent(in) :: display_style !! Style of the output display + ! Internals + character(STRMAX) :: errmsg + + select case(display_style) + case ('STANDARD') + self%display_unit = OUTPUT_UNIT !! stdout from iso_fortran_env + self%compact_display = .false. + case ('COMPACT') + open(unit=SWIFTEST_LOG_OUT, file=SWIFTEST_LOG_FILE, status='replace', err = 667, iomsg = errmsg) + self%display_unit = SWIFTEST_LOG_OUT + self%compact_display = .true. + case default + write(*,*) display_style, " is an unknown display style" + call util_exit(USAGE) + end select + + self%display_style = display_style + + return + + 667 continue + write(*,*) "Error opening swiftest log file: " // trim(adjustl(errmsg)) + call util_exit(FAILURE) + end subroutine io_set_display_param + + module subroutine io_toupper(string) !! author: David A. Minton !! @@ -1980,9 +2002,9 @@ module subroutine io_write_discard(self, param) case('APPEND') open(unit=LUN, file=param%discard_out, status='OLD', position='APPEND', form='FORMATTED', err=667, iomsg=errmsg) case('NEW', 'REPLACE', 'UNKNOWN') - open(unit=LUN, file=param%discard_out, status=param%out_stat, form='FORMATTED', err=667, iomsg=errmsg) + open(unit=LUN, file=param%discard_out, status=out_stat, form='FORMATTED', err=667, iomsg=errmsg) case default - write(*,*) 'Invalid status code for OUT_STAT: ',trim(adjustl(param%out_stat)) + write(*,*) 'Invalid status code for OUT_STAT: ',trim(adjustl(out_stat)) call util_exit(FAILURE) end select lfirst = .false. diff --git a/src/main/swiftest_driver.f90 b/src/main/swiftest_driver.f90 index 7b97eea43..ee8fda1f1 100644 --- a/src/main/swiftest_driver.f90 +++ b/src/main/swiftest_driver.f90 @@ -22,6 +22,7 @@ program swiftest_driver class(swiftest_parameters), allocatable :: param !! Run configuration parameters integer(I4B) :: 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"}). Default is "STANDARD" integer(I4B) :: ierr !! I/O error code integer(I8B) :: iloop !! Loop counter integer(I8B) :: idump !! Dump cadence counter @@ -36,14 +37,12 @@ program swiftest_driver '"; Number of active pl, tp = ", I5, ", ", I5)' character(*), parameter :: symbastatfmt = '("Time = ", ES12.5, "; fraction done = ", F6.3, ' // & '"; Number of active plm, pl, tp = ", I5, ", ", I5, ", ", I5)' - character(*), parameter :: pbarfmt = '("Time = ", ES12.5," of ",ES12.5)' + character(*), parameter :: pbarfmt = '("Time = ", G9.2," of ",G9.2)' character(len=64) :: pbarmessage - ierr = io_get_args(integrator, param_file_name) - if (ierr /= 0) then - write(*,*) 'Error reading in arguments from the command line' - call util_exit(FAILURE) - end if + + call io_get_args(integrator, param_file_name, display_style) + !> Read in the user-defined parameters file and the initial conditions of the system select case(integrator) case(symba) @@ -52,17 +51,28 @@ program swiftest_driver allocate(swiftest_parameters :: param) end select param%integrator = integrator + call param%set_display(display_style) + + !> Define the maximum number of threads + nthreads = 1 ! In the *serial* case + !$ nthreads = omp_get_max_threads() ! In the *parallel* case + !$ write(param%display_unit,'(a)') ' OpenMP parameters:' + !$ write(param%display_unit,'(a)') ' ------------------' + !$ write(param%display_unit,'(a,i3,/)') ' Number of threads = ', nthreads + !$ if (param%compact_display) write(*,'(a,i3)') ' OpenMP: Number of threads = ',nthreads call setup_construct_system(nbody_system, param) call param%read_in(param_file_name) - associate(t => param%t, & - t0 => param%t0, & - dt => param%dt, & - tstop => param%tstop, & - istep_out => param%istep_out, & - istep_dump => param%istep_dump, & - ioutput => param%ioutput) + associate(t => param%t, & + t0 => param%t0, & + dt => param%dt, & + tstop => param%tstop, & + istep_out => param%istep_out, & + istep_dump => param%istep_dump, & + ioutput => param%ioutput, & + display_unit => param%display_unit, & + compact_display => param%compact_display) call nbody_system%initialize(param) t = t0 @@ -83,17 +93,14 @@ program swiftest_driver if (istep_out > 0) call nbody_system%write_frame(param) end if - !> Define the maximum number of threads - nthreads = 1 ! In the *serial* case - !$ nthreads = omp_get_max_threads() ! In the *parallel* case - !$ write(*,'(a)') ' OpenMP parameters:' - !$ write(*,'(a)') ' ------------------' - !$ write(*,'(a,i3,/)') ' Number of threads = ', nthreads - !write(*, *) " *************** Main Loop *************** " + + write(display_unit, *) " *************** Main Loop *************** " if (param%lrestart .and. param%lenergy) call nbody_system%conservation_report(param, lterminal=.true.) - call pbar%reset(nloops) - write(pbarmessage,fmt=pbarfmt) t0, tstop - call pbar%update(1,message=pbarmessage) + if (compact_display) then + call pbar%reset(nloops) + write(pbarmessage,fmt=pbarfmt) t0, tstop + call pbar%update(1,message=pbarmessage) + end if do iloop = 1, nloops !> Step the system forward in time call integration_timer%start() @@ -104,7 +111,7 @@ program swiftest_driver !> Evaluate any discards or collisional outcomes call nbody_system%discard(param) - call pbar%update(iloop) + if (compact_display) call pbar%update(iloop) !> If the loop counter is at the output cadence value, append the data file with a single frame if (istep_out > 0) then @@ -115,19 +122,21 @@ program swiftest_driver tfrac = (param%t - param%t0) / (param%tstop - param%t0) - ! select type(pl => nbody_system%pl) - ! class is (symba_pl) - ! write(*, symbastatfmt) param%t, tfrac, pl%nplm, pl%nbody, nbody_system%tp%nbody - ! class default - ! write(*, statusfmt) param%t, tfrac, pl%nbody, nbody_system%tp%nbody - ! end select + select type(pl => nbody_system%pl) + class is (symba_pl) + write(display_unit, symbastatfmt) param%t, tfrac, pl%nplm, pl%nbody, nbody_system%tp%nbody + class default + write(display_unit, statusfmt) param%t, tfrac, pl%nbody, nbody_system%tp%nbody + end select if (param%lenergy) call nbody_system%conservation_report(param, lterminal=.true.) - !call integration_timer%report(message="Integration steps:", nsubsteps=istep_out) - !call integration_timer%reset() + call integration_timer%report(message="Integration steps:", unit=display_unit, nsubsteps=istep_out) + call integration_timer%reset() iout = istep_out - write(pbarmessage,fmt=pbarfmt) t, tstop - call pbar%update(1,message=pbarmessage) + if (compact_display) then + write(pbarmessage,fmt=pbarfmt) t, tstop + call pbar%update(1,message=pbarmessage) + end if end if end if diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 6bbcb537b..e499f8332 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -72,6 +72,7 @@ module swiftest_classes character(NAMELEN) :: interaction_loops = "ADAPTIVE" !! Method used to compute interaction loops. Options are "TRIANGULAR", "FLAT", or "ADAPTIVE" character(NAMELEN) :: encounter_check_plpl = "ADAPTIVE" !! Method used to compute pl-pl encounter checks. Options are "TRIANGULAR", "SORTSWEEP", or "ADAPTIVE" character(NAMELEN) :: encounter_check_pltp = "ADAPTIVE" !! Method used to compute pl-tp encounter checks. Options are "TRIANGULAR", "SORTSWEEP", or "ADAPTIVE" + ! The following are used internally, and are not set by the user, but instead are determined by the input value of INTERACTION_LOOPS logical :: lflatten_interactions = .false. !! Use the flattened upper triangular matrix for pl-pl interaction loops logical :: ladaptive_interactions = .false. !! Adaptive interaction loop is turned on (choose between TRIANGULAR and FLAT based on periodic timing tests) @@ -104,6 +105,10 @@ module swiftest_classes logical :: lfirstkick = .true. !! Initiate the first kick in a symplectic step logical :: lrestart = .false. !! Indicates whether or not this is a restarted run + character(len=:), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT"}). Default is "STANDARD" + integer(I4B) :: display_unit !! File unit number for display (either to stdout or to a log file) + logical :: compact_display = .false. !! Turns on the compact display + ! Future features not implemented or in development logical :: lgr = .false. !! Turn on GR logical :: lyarkovsky = .false. !! Turn on Yarkovsky effect @@ -111,10 +116,11 @@ module swiftest_classes type(netcdf_parameters) :: nciu !! Object containing NetCDF parameters contains - procedure :: reader => io_param_reader - procedure :: writer => io_param_writer - procedure :: dump => io_dump_param - procedure :: read_in => io_read_in_param + procedure :: reader => io_param_reader + procedure :: writer => io_param_writer + procedure :: dump => io_dump_param + procedure :: read_in => io_read_in_param + procedure :: set_display => io_set_display_param end type swiftest_parameters @@ -621,12 +627,12 @@ module subroutine io_dump_system(self, param) class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine io_dump_system - module function io_get_args(integrator, param_file_name) result(ierr) + 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 - integer(I4B) :: ierr !! I/O error code - end function io_get_args + character(len=:), allocatable :: 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) implicit none @@ -794,17 +800,23 @@ module subroutine io_read_particle_info_system(self, param) class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine io_read_particle_info_system - module subroutine io_write_discard(self, param) + module subroutine io_set_display_param(self, display_style) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - end subroutine io_write_discard + class(swiftest_parameters), intent(inout) :: self !! Current run configuration parameters + character(*), intent(in) :: display_style !! Style of the output display + end subroutine io_set_display_param module subroutine io_toupper(string) implicit none character(*), intent(inout) :: string !! String to make upper case end subroutine io_toupper + module subroutine io_write_discard(self, param) + implicit none + class(swiftest_nbody_system), intent(inout) :: self !! Swiftest system object + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + end subroutine io_write_discard + module subroutine io_write_frame_body(self, iu, param) implicit none class(swiftest_body), intent(in) :: self !! Swiftest body object diff --git a/src/modules/swiftest_globals.f90 b/src/modules/swiftest_globals.f90 index f6644a302..dff9cad56 100644 --- a/src/modules/swiftest_globals.f90 +++ b/src/modules/swiftest_globals.f90 @@ -81,11 +81,6 @@ module swiftest_globals integer(I4B), parameter :: USAGE = -2 !! Symbolic name for function return/flag code for printing the usage message integer(I4B), parameter :: HELP = -3 !! Symbolic name for function return/flag code for printing the usage message - character(*), parameter :: SUCCESS_MSG = '(/, "Normal termination of Swiftest (version ", f3.1, ")")' - character(*), parameter :: FAIL_MSG = '(/, "Terminating Swiftest (version ", f3.1, ") due to error!!")' - character(*), parameter :: USAGE_MSG = '("Usage: swiftest [bs|helio|ra15|rmvs|symba|tu4|whm] ")' - character(*), parameter :: HELP_MSG = USAGE_MSG - integer(I4B), parameter :: ELLIPSE = -1 !! Symbolic names for orbit types - ellipse integer(I4B), parameter :: PARABOLA = 0 !! Symbolic names for orbit types - parabola integer(I4B), parameter :: HYPERBOLA = 1 !! Symbolic names for orbit types - hyperbola @@ -123,11 +118,13 @@ module swiftest_globals !> Standard file names integer(I4B), parameter :: NDUMPFILES = 2 - character(*), dimension(2), parameter :: DUMP_CB_FILE = ['dump_cb1.bin', 'dump_cb2.bin' ] - character(*), dimension(2), parameter :: DUMP_PL_FILE = ['dump_pl1.bin', 'dump_pl2.bin' ] - character(*), dimension(2), parameter :: DUMP_TP_FILE = ['dump_tp1.bin', 'dump_tp2.bin' ] - character(*), dimension(2), parameter :: DUMP_NC_FILE = ['dump_bin1.nc', 'dump_bin2.nc' ] + character(*), dimension(2), parameter :: DUMP_CB_FILE = ['dump_cb1.bin', 'dump_cb2.bin' ] + character(*), dimension(2), parameter :: DUMP_PL_FILE = ['dump_pl1.bin', 'dump_pl2.bin' ] + character(*), dimension(2), parameter :: DUMP_TP_FILE = ['dump_tp1.bin', 'dump_tp2.bin' ] + character(*), dimension(2), parameter :: DUMP_NC_FILE = ['dump_bin1.nc', 'dump_bin2.nc' ] character(*), dimension(2), parameter :: DUMP_PARAM_FILE = ['dump_param1.in', 'dump_param2.in'] + character(*), parameter :: SWIFTEST_LOG_FILE = "swiftest.log" !! Name of file to use to log output when using "COMPACT" display style + integer(I4B), parameter :: SWIFTEST_LOG_OUT = 33 !! File unit for log file when using "COMPACT" display style !> Default file names that can be changed by the user in the parameters file character(*), parameter :: CB_INFILE = 'cb.in' diff --git a/src/modules/walltime_classes.f90 b/src/modules/walltime_classes.f90 index 0dc3f2892..536272b44 100644 --- a/src/modules/walltime_classes.f90 +++ b/src/modules/walltime_classes.f90 @@ -29,6 +29,8 @@ module walltime_classes integer(I8B) :: count_stop_step !! Value of the clock ticker at the end of a timed step integer(I8B) :: count_pause !! Value of the clock ticker at the end of a timed step real(DP) :: wall_step !! Value of the step elapsed time + real(DP) :: wall_main !! Value of the main clock elapsed time + real(DP) :: wall_per_substep !! Value of time per substep logical :: main_is_started = .false. !! Logical flag indicating whether or not the main timer has been reset or not logical :: is_paused = .false. !! Logical flag indicating whether or not the timer is paused @@ -60,10 +62,11 @@ module walltime_classes end type interaction_timer interface - module subroutine walltime_report(self, message, nsubsteps) + module subroutine walltime_report(self, message, unit, nsubsteps) implicit none class(walltimer), intent(inout) :: self !! Walltimer object character(len=*), intent(in) :: message !! Message to prepend to the wall time terminal output + integer(I4B), intent(in) :: unit !! Output file unit for report text to be directed integer(I4B), optional, intent(in) :: nsubsteps !! Number of substeps used to compute the time per step end subroutine walltime_report diff --git a/src/util/util_exit.f90 b/src/util/util_exit.f90 index 61dacdf99..65d92206d 100644 --- a/src/util/util_exit.f90 +++ b/src/util/util_exit.f90 @@ -23,6 +23,10 @@ module subroutine util_exit(code) integer(I4B), intent(in) :: code ! Internals character(*), parameter :: BAR = '("------------------------------------------------")' + character(*), parameter :: SUCCESS_MSG = '(/, "Normal termination of Swiftest (version ", f3.1, ")")' + character(*), parameter :: FAIL_MSG = '(/, "Terminating Swiftest (version ", f3.1, ") due to error!!")' + character(*), parameter :: USAGE_MSG = '("Usage: swiftest [bs|helio|ra15|rmvs|symba|tu4|whm] [standard|compact|NONE]")' + character(*), parameter :: HELP_MSG = USAGE_MSG select case(code) case(SUCCESS) diff --git a/src/walltime/walltime.f90 b/src/walltime/walltime.f90 index 6c53e2276..104b63d95 100644 --- a/src/walltime/walltime.f90 +++ b/src/walltime/walltime.f90 @@ -38,7 +38,7 @@ module subroutine walltime_stop(self) end subroutine walltime_stop - module subroutine walltime_report(self, message, nsubsteps) + module subroutine walltime_report(self, message, unit, nsubsteps) !! author: David A. Minton !! !! Prints the elapsed time information to the terminal @@ -46,6 +46,7 @@ module subroutine walltime_report(self, message, nsubsteps) ! Arguments class(walltimer), intent(inout) :: self !! Walltimer object character(len=*), intent(in) :: message !! Message to prepend to the wall time terminal output + integer(I4B), intent(in) :: unit !! Output file unit for report text to be directed integer(I4B), optional, intent(in) :: nsubsteps !! Number of substeps used to compute the time per step ! Internals character(len=*), parameter :: nosubstepfmt = '" Total wall time: ", es12.5, "; Interval wall time: ", es12.5 ' @@ -53,9 +54,6 @@ module subroutine walltime_report(self, message, nsubsteps) 'Interval wall time/step: ", es12.5' character(len=STRMAX) :: fmt integer(I8B) :: count_delta_step, count_delta_main, count_now - real(DP) :: wall_main !! Value of total elapsed time at the end of a timed step - real(DP) :: wall_step !! Value of elapsed time since the start of a timed step - real(DP) :: wall_per_substep !! Value of time per substep if (.not.self%main_is_started) then write(*,*) "Wall timer error: The step finish time cannot be calculated because the timer is not started!" @@ -65,18 +63,17 @@ module subroutine walltime_report(self, message, nsubsteps) call system_clock(count_now) count_delta_main = count_now - self%count_start_main count_delta_step = count_now - self%count_start_step - wall_main = count_delta_main / (self%count_rate * 1.0_DP) - wall_step = count_delta_step / (self%count_rate * 1.0_DP) + self%wall_main = count_delta_main / (self%count_rate * 1.0_DP) + self%wall_step = count_delta_step / (self%count_rate * 1.0_DP) if (present(nsubsteps)) then - wall_per_substep = wall_step / nsubsteps + self%wall_per_substep = self%wall_step / nsubsteps fmt = '("' // adjustl(message) // '",' // substepfmt // ')' - write(*,trim(adjustl(fmt))) wall_main, self%wall_step, wall_per_substep + write(unit,trim(adjustl(fmt))) self%wall_main, self%wall_step, self%wall_per_substep else fmt = '("' // adjustl(message) // '",' // nosubstepfmt // ')' - write(*,trim(adjustl(fmt))) wall_main, self%wall_step + write(unit,trim(adjustl(fmt))) self%wall_main, self%wall_step end if - return end subroutine walltime_report @@ -92,6 +89,7 @@ module subroutine walltime_reset(self) self%is_paused = .false. self%wall_step = 0.0_DP + self%wall_per_substep = 0.0_DP return end subroutine walltime_reset @@ -107,6 +105,7 @@ module subroutine walltime_start_main(self) call system_clock(self%count_start_main, self%count_rate, self%count_max) self%main_is_started = .true. + self%wall_main = 0.0_DP return end subroutine walltime_start_main @@ -123,7 +122,6 @@ module subroutine walltime_start(self) ! Internals integer(I8B) :: count_resume, count_delta - if (.not.self%main_is_started) then call self%reset() call self%start_main()