diff --git a/examples/.gitignore b/examples/.gitignore index 829298555..9b6c85b05 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -8,3 +8,4 @@ !helio_gr_test !solar_impact !whm_gr_test +!spherical_harmonics_cb diff --git a/examples/Basic_Simulation/output_reader.py b/examples/Basic_Simulation/output_reader.py index a46b6cefc..56f19362c 100644 --- a/examples/Basic_Simulation/output_reader.py +++ b/examples/Basic_Simulation/output_reader.py @@ -25,7 +25,6 @@ """ import swiftest -import xarray as xr import matplotlib.pyplot as plt # Read in the simulation output and store it as an Xarray dataset. diff --git a/examples/spherical_harmonics_cb/.gitignore b/examples/spherical_harmonics_cb/.gitignore new file mode 100644 index 000000000..94eee0157 --- /dev/null +++ b/examples/spherical_harmonics_cb/.gitignore @@ -0,0 +1,3 @@ +!spherical_harmonics_cb.py +!J2_test_tp.py +!J2_test_pl_and_tp.py \ No newline at end of file diff --git a/examples/spherical_harmonics_cb/J2_test_pl_and_tp.py b/examples/spherical_harmonics_cb/J2_test_pl_and_tp.py new file mode 100644 index 000000000..62bd7228a --- /dev/null +++ b/examples/spherical_harmonics_cb/J2_test_pl_and_tp.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 + +""" + Copyright 2024 - The Minton Group at Purdue University + This file is part of Swiftest. + Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with Swiftest. + If not, see: https://www.gnu.org/licenses. +""" + +""" +Generates and runs a set of Swiftest input files from initial conditions for the Spherical Harmonics features with the WHM integrator. +""" + +import swiftest +import numpy as np + +seed = 123 +rng = np.random.default_rng(seed=seed) + + +# Central Body Parameters (just an oblate sphere to test) +cb_mass = 6.1e18 # kg +cb_a = 160 # km +cb_b = 160 # km +cb_c = 90 # km +cb_volume = 4.0 / 3 * np.pi * cb_a*cb_b*cb_c**3 # km^3 +cb_density = cb_mass / cb_volume +cb_T_rotation = 7.004 / 24.0 # converting from hours to julian days (TU) +cb_rot = [[0, 0, 360.0 / cb_T_rotation]] # degrees/d + +# Add 1 user-defined test particle. +ntp = 1 + +name_tp = ["TestParticle_01"] +a_tp = 400 +e_tp = 0.05 +inc_tp = 10 +capom_tp = 0.0 +omega_tp = 0.0 +capm_tp = 0.0 + + +# Add 1 user-defined massive particle +npl = 1 +density_pl = cb_density + +name_pl = ["MassiveBody_01"] +a_pl = 300.0 +e_pl = 0.03 +inc_pl = 0.001 +capom_pl = 90.0 +omega_pl = 90.0 +capm_pl = 90.0 +R_pl = 1.0 +M_pl = 4.0 / 3 * np.pi * R_pl**3 * density_pl +Ip_pl = np.full((npl,3),0.4,) +rot_pl = np.zeros((npl,3)) +mtiny = 0.1 * np.max(M_pl) + + +# Extract the spherical harmonics coefficients (c_lm) from axes measurements +# +# The user can pass an optional reference radius at which the coefficients are calculated. If not provided, SHTOOLS +# calculates the reference radius. If lref_radius = True, the function returns the reference radius used. +# We recommend setting passing and setting a reference radius. Coefficients are geodesy (4-pi) normalised. + +c_lm, cb_radius = swiftest.clm_from_ellipsoid(mass = cb_mass, density = cb_density, a = cb_a, b = cb_b, c = cb_c, lmax = 6, lref_radius = True) + +# extracting only the J2 terms +tmp20 = c_lm[0, 2, 0] # c_20 = -J2 +c_lm = np.zeros(np.shape(c_lm)) +c_lm[0, 2, 0] = tmp20 + +J2 = -tmp20 * np.sqrt(5) # unnormalised J2 term +j2rp2 = J2 * cb_radius**2 + +# set up swiftest simulation with relevant units (here they are km, days, and kg) +sim_shgrav = swiftest.Simulation(simdir="shgrav",DU2M = 1e3, TU = 'd', MU = 'kg') + +sim_shgrav.clean() +# Use the shgrav version where you input a set of spherical harmonics coefficients +sim_shgrav.add_body(name = 'OblateBody', mass = cb_mass, rot = cb_rot, radius = cb_radius, c_lm = c_lm) +sim_shgrav.add_body(name=name_tp, a=a_tp, e=e_tp, inc=inc_tp, capom=capom_tp, omega=omega_tp, capm=capm_tp) +sim_shgrav.add_body(name=name_pl, a=a_pl, e=e_pl, inc=inc_pl, capom=capom_pl, omega=omega_pl, capm=capm_pl, mass=M_pl, radius=R_pl, Ip=Ip_pl, rot=rot_pl) +sim_shgrav.run(tstart=0.0, tstop=10.0, dt=0.01, tstep_out=10.0, dump_cadence=0, mtiny=mtiny, integrator='symba') + +# Use the original "oblate" version where you pass J2 (and/or J4) +sim_obl = swiftest.Simulation(simdir="obl", DU2M = 1e3, TU='d', MU='kg') +sim_obl.clean() +sim_obl.add_body(name = 'OblateBody', mass = cb_mass, rot = cb_rot, radius = cb_radius, J2 = j2rp2) +sim_obl.add_body(name=name_tp, a=a_tp, e=e_tp, inc=inc_tp, capom=capom_tp, omega=omega_tp, capm=capm_tp) +sim_obl.add_body(name=name_pl, a=a_pl, e=e_pl, inc=inc_pl, capom=capom_pl, omega=omega_pl, capm=capm_pl, mass=M_pl, radius=R_pl, Ip=Ip_pl, rot=rot_pl) +sim_obl.run(tstart=0.0, tstop=10.0, dt=0.01, tstep_out=10.0, dump_cadence=0, mtiny=mtiny, integrator='symba') + +diff_vars = ['a','e','inc','capom','omega','capm','rh','vh'] +ds_diff = sim_shgrav.data[diff_vars] - sim_obl.data[diff_vars] +ds_diff /= sim_obl.data[diff_vars] + +print(ds_diff.isel(time=-1,name=-2)) +print(ds_diff.isel(time=-1,name=-1)) + diff --git a/examples/spherical_harmonics_cb/J2_test_tp.py b/examples/spherical_harmonics_cb/J2_test_tp.py new file mode 100644 index 000000000..1c433f0d3 --- /dev/null +++ b/examples/spherical_harmonics_cb/J2_test_tp.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 + +""" + Copyright 2024 - The Minton Group at Purdue University + This file is part of Swiftest. + Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with Swiftest. + If not, see: https://www.gnu.org/licenses. +""" + +""" +Generates and runs a set of Swiftest input files from initial conditions for the Spherical Harmonics features with the WHM integrator. +""" + +import swiftest +import numpy as np + +seed = 123 +rng = np.random.default_rng(seed=seed) + + +# Central Body Parameters (just an oblate sphere to test) +cb_mass = 6.1e18 # kg +cb_a = 160 # km +cb_b = 160 # km +cb_c = 90 # km +cb_volume = 4.0 / 3 * np.pi * cb_a*cb_b*cb_c**3 # km^3 +cb_density = cb_mass / cb_volume +cb_T_rotation = 7.004 / 24.0 # converting from hours to julian days (TU) +cb_rot = [[0, 0, 360.0 / cb_T_rotation]] # degrees/d + +# Add 1 user-defined test particle. +ntp = 1 + +name_tp = ["TestParticle_01"] +a_tp = 300 +e_tp = 0.05 +inc_tp = 10 +capom_tp = 0.0 +omega_tp = 0.0 +capm_tp = 0.0 + +# Extract the spherical harmonics coefficients (c_lm) from axes measurements +# +# The user can pass an optional reference radius at which the coefficients are calculated. If not provided, SHTOOLS +# calculates the reference radius. If lref_radius = True, the function returns the reference radius used. +# We recommend setting passing and setting a reference radius. Coefficients are geodesy (4-pi) normalised. + +c_lm, cb_radius = swiftest.clm_from_ellipsoid(mass = cb_mass, density = cb_density, a = cb_a, b = cb_b, c = cb_c, lmax = 6, lref_radius = True) + +# extracting only the J2 terms +tmp20 = c_lm[0, 2, 0] # c_20 = -J2 +c_lm = np.zeros(np.shape(c_lm)) +c_lm[0, 2, 0] = tmp20 + +J2 = -tmp20 * np.sqrt(5) # unnormalised J2 term +j2rp2 = J2 * cb_radius**2 + +# set up swiftest simulation with relevant units (here they are km, days, and kg) +sim_shgrav = swiftest.Simulation(simdir="shgrav",DU2M = 1e3, TU = 'd', MU = 'kg') + +sim_shgrav.clean() +# Use the shgrav version where you input a set of spherical harmonics coefficients +sim_shgrav.add_body(name = 'OblateBody', mass = cb_mass, rot = cb_rot, radius = cb_radius, c_lm = c_lm) +sim_shgrav.add_body(name=name_tp, a=a_tp, e=e_tp, inc=inc_tp, capom=capom_tp, omega=omega_tp, capm=capm_tp) +sim_shgrav.run(tstart=0.0, tstop=10.0, dt=0.01, tstep_out=10.0, dump_cadence=0, integrator='whm') + +# Use the original "oblate" version where you pass J2 (and/or J4) +sim_obl = swiftest.Simulation(simdir="obl", DU2M = 1e3, TU='d', MU='kg') +sim_obl.clean() +sim_obl.add_body(name = 'OblateBody', mass = cb_mass, rot = cb_rot, radius = cb_radius, J2 = j2rp2) +sim_obl.add_body(name=name_tp, a=a_tp, e=e_tp, inc=inc_tp, capom=capom_tp, omega=omega_tp, capm=capm_tp) +sim_obl.run(tstart=0.0, tstop=10.0, dt=0.01, tstep_out=10.0, dump_cadence=0, integrator='whm') + +diff_vars = ['a','e','inc','capom','omega','capm','rh','vh'] +ds_diff = sim_shgrav.data[diff_vars] - sim_obl.data[diff_vars] +ds_diff /= sim_obl.data[diff_vars] + +print(ds_diff.isel(time=-1,name=-1)) + diff --git a/examples/spherical_harmonics_cb/spherical_harmonics_cb.py b/examples/spherical_harmonics_cb/spherical_harmonics_cb.py new file mode 100644 index 000000000..83df9042a --- /dev/null +++ b/examples/spherical_harmonics_cb/spherical_harmonics_cb.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + +""" + Copyright 2024 - The Minton Group at Purdue University + This file is part of Swiftest. + Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with Swiftest. + If not, see: https://www.gnu.org/licenses. +""" + +""" +Generates and runs a set of Swiftest input files from initial conditions for the Spherical Harmonics features with the +SyMBA integrator. Using Chariklo as the example body with axes measurements taken from Leiva, et al (2017) (Jacobi +Ellipsoid model). All simulation outputs are stored in the /simdata subdirectory. + +""" + +import swiftest +import numpy as np + +seed = 123 +rng = np.random.default_rng(seed=seed) + +# set up swiftest simulation with relevant units (here they are km, days, and kg) +sim = swiftest.Simulation(DU2M = 1e3, TU = 'd', MU = 'kg') +sim.clean() + +# Central Body Parameters (Chariklo parameters from Leiva, et al (2017) (Jacobi Ellipsoid model)) +cb_mass = 6.1e18 # kg +cb_radius = 123 # km +cb_a = 157 # km +cb_b = 139 # km +cb_c = 86 # km +cb_volume = 4.0 / 3 * np.pi * cb_radius**3 # km^3 +cb_density = cb_mass / cb_volume +cb_T_rotation = 7.004 / 24.0 # converting from hours to julian days (TU) +cb_rot = [[0, 0, 360.0 / cb_T_rotation]] # degrees/d + +# Extract the spherical harmonics coefficients (c_lm) from axes measurements +# +# The user can pass an optional reference radius at which the coefficients are calculated. If not provided, SHTOOLS +# calculates the reference radius. If lref_radius = True, the function returns the reference radius used. +# We recommend setting passing and setting a reference radius. Coefficients are geodesy (4-pi) normalised. + +c_lm, cb_radius = swiftest.clm_from_ellipsoid(mass = cb_mass, density = cb_density, a = cb_a, b = cb_b, c = cb_c, lmax = 6, lref_radius = True, ref_radius = cb_radius) + +# Add the central body +# The user can pass the c_lm coefficients directly to the add_body method if they do not wish to use the clm_from_ellipsoid method. +sim.add_body(name = 'Chariklo', mass = cb_mass, rot = cb_rot, radius = cb_radius, c_lm = c_lm) + +# Add user-defined massive bodies +npl = 5 +density_pl = cb_density + +name_pl = ["SemiBody_01", "SemiBody_02", "SemiBody_03", "SemiBody_04", "SemiBody_05"] +a_pl = rng.uniform(250, 400, npl) +e_pl = rng.uniform(0.0, 0.05, npl) +inc_pl = rng.uniform(0.0, 10, npl) +capom_pl = rng.uniform(0.0, 360.0, npl) +omega_pl = rng.uniform(0.0, 360.0, npl) +capm_pl = rng.uniform(0.0, 360.0, npl) +R_pl = np.array([0.5, 1.0, 1.2, 0.75, 0.8]) +M_pl = 4.0 / 3 * np.pi * R_pl**3 * density_pl +Ip_pl = np.full((npl,3),0.4,) +rot_pl = np.zeros((npl,3)) +mtiny = 1.1 * np.max(M_pl) + +sim.add_body(name=name_pl, a=a_pl, e=e_pl, inc=inc_pl, capom=capom_pl, omega=omega_pl, capm=capm_pl, mass=M_pl, radius=R_pl, Ip=Ip_pl, rot=rot_pl) + +# Add 10 user-defined test particles. +ntp = 10 + +name_tp = ["TestParticle_01", "TestParticle_02", "TestParticle_03", "TestParticle_04", "TestParticle_05", "TestParticle_06", "TestParticle_07", "TestParticle_08", "TestParticle_09", "TestParticle_10"] +a_tp = rng.uniform(250, 400, ntp) +e_tp = rng.uniform(0.0, 0.05, ntp) +inc_tp = rng.uniform(0.0, 10, ntp) +capom_tp = rng.uniform(0.0, 360.0, ntp) +omega_tp = rng.uniform(0.0, 360.0, ntp) +capm_tp = rng.uniform(0.0, 360.0, ntp) + +sim.add_body(name=name_tp, a=a_tp, e=e_tp, inc=inc_tp, capom=capom_tp, omega=omega_tp, capm=capm_tp) +sim.set_parameter(tstart=0.0, tstop=10.0, dt=0.01, istep_out=10, dump_cadence=0, compute_conservation_values=True, mtiny=mtiny) + +# Display the run configuration parameters. +sim.get_parameter() + +# Run the simulation. Arguments may be defined here or thorugh the swiftest.Simulation() method. +sim.run() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bec5aa743..89eaadeee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,6 +33,7 @@ SET(STRICT_MATH_FILES ${SRC}/operator/operator_unit.f90 ${SRC}/rmvs/rmvs_kick.f90 ${SRC}/rmvs/rmvs_step.f90 + ${SRC}/shgrav/shgrav_accel.f90 ${SRC}/swiftest/swiftest_drift.f90 ${SRC}/swiftest/swiftest_gr.f90 ${SRC}/swiftest/swiftest_io.f90 @@ -40,7 +41,6 @@ SET(STRICT_MATH_FILES ${SRC}/swiftest/swiftest_user.f90 ${SRC}/swiftest/swiftest_obl.f90 ${SRC}/swiftest/swiftest_orbel.f90 - ${SRC}/swiftest/swiftest_sph.f90 ${SRC}/symba/symba_drift.f90 ${SRC}/symba/symba_gr.f90 ${SRC}/symba/symba_kick.f90 diff --git a/src/base/base_module.f90 b/src/base/base_module.f90 index 6f0821b70..705e90c5f 100644 --- a/src/base/base_module.f90 +++ b/src/base/base_module.f90 @@ -8,10 +8,10 @@ ! If not, see: https://www.gnu.org/licenses. module base - !! author: The Purdue Swiftest Team - David A. Minton, Carlisle A. Wishard, Jennifer L.L. Pouplin, and Jacob R. Elliott - !! - !! Base type definitions. This allows the collision and encounter modules to be defined before the swiftest module. - !! + !! author: The Purdue Swiftest Team - David A. Minton, Carlisle A. Wishard, Jennifer L.L. Pouplin, and Jacob R. Elliott + !! + !! Base type definitions. This allows the collision and encounter modules to be defined before the swiftest module. + !! use globals #ifdef COARRAY use coarray @@ -22,109 +22,184 @@ module base !> User defined parameters that are read in from the parameters input file. !> Each paramter is initialized to a default values. type, abstract :: base_parameters - character(STRMAX) :: integrator !! Name of the nbody integrator used - character(STRMAX) :: param_file_name !! The name of the parameter file - real(DP) :: t0 = 0.0_DP !! Integration reference time - real(DP) :: tstart = -1.0_DP !! Integration start time - real(DP) :: tstop = -1.0_DP !! Integration stop time - real(DP) :: dt = -1.0_DP !! Time step - integer(I8B) :: iloop = 0_I8B !! Main loop counter - integer(I8B) :: nloops = 0_I8B !! Total number of loops to execute - integer(I8B) :: istart = 0_I8B !! Starting index for loop counter - integer(I4B) :: iout = 0 !! Output cadence counter - integer(I4B) :: idump = 0 !! Dump cadence counter - integer(I4B) :: nout = 0 !! Current output step - integer(I4B) :: istep = 0 !! Current value of istep (used for time stretching) - character(STRMAX) :: incbfile = CB_INFILE !! Name of input file for the central body - character(STRMAX) :: inplfile = PL_INFILE !! Name of input file for massive bodies - character(STRMAX) :: intpfile = TP_INFILE !! Name of input file for test particles - character(STRMAX) :: nc_in = NC_INFILE !! Name of system input file for NetCDF input - character(STRMAX) :: in_type = "NETCDF_DOUBLE" !! Data representation type of input data files - character(STRMAX) :: in_form = "XV" !! Format of input data files ("EL" or ["XV"]) - integer(I4B) :: istep_out = -1 !! Number of time steps between saved outputs - integer(I4B) :: nstep_out = -1 !! Total number of saved outputs - real(DP) :: fstep_out = 1.0_DP !! The output step time stretching factor - logical :: ltstretch = .false. !! Whether to employ time stretching or not - character(STRMAX) :: outfile = BIN_OUTFILE !! Name of output binary file - character(STRMAX) :: out_type = "NETCDF_DOUBLE" !! Binary format of output file - character(STRMAX) :: out_form = "XVEL" !! Data to write to output file - character(STRMAX) :: out_stat = 'NEW' !! Open status for output binary file - integer(I4B) :: dump_cadence = 10 !! Number of output steps between dumping simulation data to file - real(DP) :: rmin = -1.0_DP !! Minimum heliocentric radius for test particle - real(DP) :: rmax = -1.0_DP !! Maximum heliocentric radius for test particle - real(DP) :: rmaxu = -1.0_DP !! Maximum unbound heliocentric radius for test particle - real(DP) :: qmin = -1.0_DP !! Minimum pericenter distance for test particle - character(STRMAX) :: qmin_coord = "HELIO" !! Coordinate frame to use for qmin (["HELIO"] or "BARY") - real(DP) :: qmin_alo = -1.0_DP !! Minimum semimajor axis for qmin - real(DP) :: qmin_ahi = -1.0_DP !! Maximum semimajor axis for qmin - real(QP) :: MU2KG = -1.0_QP !! Converts mass units to grams - real(QP) :: TU2S = -1.0_QP !! Converts time units to seconds - real(QP) :: DU2M = -1.0_QP !! Converts distance unit to centimeters - real(DP) :: GU = -1.0_DP !! Universal gravitational constant in the system units - real(DP) :: inv_c2 = -1.0_DP !! Inverse speed of light squared in the system units - real(DP) :: GMTINY = -1.0_DP !! Smallest G*mass that is fully gravitating - real(DP) :: min_GMfrag = -1.0_DP !! Smallest G*mass that can be produced in a fragmentation event - real(DP) :: nfrag_reduction = 30.0_DP !! Reduction factor for limiting the number of collision fragments - integer(I4B), dimension(:), allocatable :: seed !! Random seeds for fragmentation modeling - logical :: lmtiny_pl = .false. !! Include semi-interacting massive bodies - character(STRMAX) :: collision_model = "MERGE" !! The Coll - character(STRMAX) :: encounter_save = "NONE" !! Indicate if and how encounter data should be saved - logical :: lenc_save_trajectory = .false. !! Indicates that when encounters are saved, the full trajectory - !! through recursion steps are saved - logical :: lenc_save_closest = .false. !! Indicates that when encounters are saved, the closest approach - !! distance between pairs of bodies is saved - 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" - logical :: lcoarray = .false. !! Use Coarrays for test particle parallelization. + character(STRMAX) :: integrator + !! Name of the nbody integrator used + character(STRMAX) :: param_file_name + !! The name of the parameter file + real(DP) :: t0 = 0.0_DP + !! Integration reference time + real(DP) :: tstart = -1.0_DP + !! Integration start time + real(DP) :: tstop = -1.0_DP + !! Integration stop time + real(DP) :: dt = -1.0_DP + !! Time step + integer(I8B) :: iloop = 0_I8B + !! Main loop counter + integer(I8B) :: nloops = 0_I8B + !! Total number of loops to execute + integer(I8B) :: istart = 0_I8B + !! Starting index for loop counter + integer(I4B) :: iout = 0 + !! Output cadence counter + integer(I4B) :: idump = 0 + !! Dump cadence counter + integer(I4B) :: nout = 0 + !! Current output step + integer(I4B) :: istep = 0 + !! Current value of istep (used for time stretching) + character(STRMAX) :: incbfile = CB_INFILE + !! Name of input file for the central body + character(STRMAX) :: inplfile = PL_INFILE + !! Name of input file for massive bodies + character(STRMAX) :: intpfile = TP_INFILE + !! Name of input file for test particles + character(STRMAX) :: nc_in = NC_INFILE + !! Name of system input file for NetCDF input + character(STRMAX) :: in_type = "NETCDF_DOUBLE" + !! Data representation type of input data files + character(STRMAX) :: in_form = "XV" + !! Format of input data files ("EL" or ["XV"]) + integer(I4B) :: istep_out = -1 + !! Number of time steps between saved outputs + integer(I4B) :: nstep_out = -1 + !! Total number of saved outputs + real(DP) :: fstep_out = 1.0_DP + !! The output step time stretching factor + logical :: ltstretch = .false. + !! Whether to employ time stretching or not + character(STRMAX) :: outfile = BIN_OUTFILE + !! Name of output binary file + character(STRMAX) :: out_type = "NETCDF_DOUBLE" + !! Binary format of output file + character(STRMAX) :: out_form = "XVEL" + !! Data to write to output file + character(STRMAX) :: out_stat = 'NEW' + !! Open status for output binary file + integer(I4B) :: dump_cadence = 10 + !! Number of output steps between dumping simulation data to file + real(DP) :: rmin = -1.0_DP + !! Minimum heliocentric radius for test particle + real(DP) :: rmax = -1.0_DP + !! Maximum heliocentric radius for test particle + real(DP) :: rmaxu = -1.0_DP + !! Maximum unbound heliocentric radius for test particle + real(DP) :: qmin = -1.0_DP + !! Minimum pericenter distance for test particle + character(STRMAX) :: qmin_coord = "HELIO" + !! Coordinate frame to use for qmin (["HELIO"] or "BARY") + real(DP) :: qmin_alo = -1.0_DP + !! Minimum semimajor axis for qmin + real(DP) :: qmin_ahi = -1.0_DP + !! Maximum semimajor axis for qmin + real(QP) :: MU2KG = -1.0_QP + !! Converts mass units to grams + real(QP) :: TU2S = -1.0_QP + !! Converts time units to seconds + real(QP) :: DU2M = -1.0_QP + !! Converts distance unit to centimeters + real(DP) :: GU = -1.0_DP + !! Universal gravitational constant in the system units + real(DP) :: inv_c2 = -1.0_DP + !! Inverse speed of light squared in the system units + real(DP) :: GMTINY = -1.0_DP + !! Smallest G*mass that is fully gravitating + real(DP) :: min_GMfrag = -1.0_DP + !! Smallest G*mass that can be produced in a fragmentation event + real(DP) :: nfrag_reduction = 30.0_DP + !! Reduction factor for limiting the number of collision fragments + integer(I4B), dimension(:), allocatable :: seed + !! Random seeds for fragmentation modeling + logical :: lmtiny_pl = .false. + !! Include semi-interacting massive bodies + character(STRMAX) :: collision_model = "MERGE" + !! The Coll + character(STRMAX) :: encounter_save = "NONE" + !! Indicate if and how encounter data should be saved + logical :: lenc_save_trajectory = .false. + !! Indicates that when encounters are saved, the full trajectory through recursion steps are saved + logical :: lenc_save_closest = .false. + !! Indicates that when encounters are saved, the closest approach distance between pairs of bodies is saved + 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" + logical :: lcoarray = .false. + !! Use Coarrays for test particle parallelization. ! The following 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 :: lencounter_sas_plpl = .false. !! Use the Sort and Sweep algorithm to prune the encounter list before checking - !! for close encounters - logical :: lencounter_sas_pltp = .false. !! Use the Sort and Sweep algorithm to prune the encounter list before checking - !! for close encounters + logical :: lflatten_interactions = .false. + !! Use the flattened upper triangular matrix for pl-pl interaction loops + logical :: lencounter_sas_plpl = .false. + !! Use the Sort and Sweep algorithm to prune the encounter list before checking for close encounters + logical :: lencounter_sas_pltp = .false. + !! Use the Sort and Sweep algorithm to prune the encounter list before checking for close encounters ! Logical flags to turn on or off various features of the code - logical :: lrhill_present = .false. !! Hill radii are given as an input rather than calculated by the code (can be used to - !! inflate close encounter regions manually) - logical :: lextra_force = .false. !! User defined force function turned on - logical :: lbig_discard = .false. !! Save big bodies on every discard - logical :: lclose = .false. !! Turn on close encounters - logical :: lenergy = .false. !! Track the total energy of the system - logical :: loblatecb = .false. !! Calculate acceleration from oblate central body (automatically turns true if nonzero J2 - !! is input) - logical :: lrotation = .false. !! Include rotation states of big bodies - logical :: ltides = .false. !! Include tidal dissipation - logical :: lshgrav = .false. !! Calculate acceleration from spherical harmonics terms for the central body - !! (automatically turns true if clm array is inputted) + logical :: lrhill_present = .false. + !! Hill radii are given as an input rather than calculated by the code (can be used to inflate close encounter regions + !! manually) + logical :: lextra_force = .false. + !! User defined force function turned on + logical :: lbig_discard = .false. + !! Save big bodies on every discard + logical :: lclose = .false. + !! Turn on close encounters + logical :: lenergy = .false. + !! Track the total energy of the system + logical :: lnon_spherical_cb = .false. + !! Calculate acceleration from oblate central body (automatically turns true if nonzero J2, J4, or c_lm is input) + logical :: lrotation = .false. + !! Include rotation states of big bodies + logical :: ltides = .false. + !! Include tidal dissipation ! Initial values to pass to the energy report subroutine (usually only used in the case of a restart, otherwise these will be ! updated with initial conditions values) - real(DP) :: E_orbit_orig = 0.0_DP !! Initial orbital energy - real(DP) :: GMtot_orig = 0.0_DP !! Initial system mass - real(DP), dimension(NDIM) :: L_total_orig = 0.0_DP !! Initial total angular momentum vector - real(DP), dimension(NDIM) :: L_orbit_orig = 0.0_DP !! Initial orbital angular momentum - real(DP), dimension(NDIM) :: L_spin_orig = 0.0_DP !! Initial spin angular momentum vector - real(DP), dimension(NDIM) :: L_escape = 0.0_DP !! Angular momentum of escaped bodies (used for bookeeping) - real(DP) :: GMescape = 0.0_DP !! Mass of bodies that escaped the system (used for bookeeping) - real(DP) :: E_collisions = 0.0_DP !! Energy lost from system due to collisions - real(DP) :: E_untracked = 0.0_DP !! Energy gained from system due to escaped bodies - logical :: lfirstenergy = .true. !! This is the first time computing energe - logical :: lfirstkick = .true. !! Initiate the first kick in a symplectic step - logical :: lrestart = .false. !! Indicates whether or not this is a restarted run - - character(NAMELEN) :: display_style !! Style of the output display {["STANDARD"], "COMPACT"}). - integer(I4B) :: display_unit = OUTPUT_UNIT !! File unit number for display (either to stdout or to a log file) - logical :: log_output = .false. !! Logs the output to file instead of displaying it on the terminal + real(DP) :: E_orbit_orig = 0.0_DP + !! Initial orbital energy + real(DP) :: GMtot_orig = 0.0_DP + !! Initial system mass + real(DP), dimension(NDIM) :: L_total_orig = 0.0_DP + !! Initial total angular momentum vector + real(DP), dimension(NDIM) :: L_orbit_orig = 0.0_DP + !! Initial orbital angular momentum + real(DP), dimension(NDIM) :: L_spin_orig = 0.0_DP + !! Initial spin angular momentum vector + real(DP), dimension(NDIM) :: L_escape = 0.0_DP + !! Angular momentum of escaped bodies (used for bookeeping) + real(DP) :: GMescape = 0.0_DP + !! Mass of bodies that escaped the system (used for bookeeping) + real(DP) :: E_collisions = 0.0_DP + !! Energy lost from system due to collisions + real(DP) :: E_untracked = 0.0_DP + !! Energy gained from system due to escaped bodies + logical :: lfirstenergy = .true. + !! This is the first time computing energe + logical :: lfirstkick = .true. + !! Initiate the first kick in a symplectic step + logical :: lrestart = .false. + !! Indicates whether or not this is a restarted run + + character(NAMELEN) :: display_style + !! Style of the output display {["STANDARD"], "COMPACT"}). + integer(I4B) :: display_unit = OUTPUT_UNIT + !! File unit number for display (either to stdout or to a log file) + logical :: log_output = .false. + !! Logs the output to file instead of displaying it on the terminal ! Future features not implemented or in development - logical :: lgr = .false. !! Turn on GR - logical :: lyarkovsky = .false. !! Turn on Yarkovsky effect - logical :: lyorp = .false. !! Turn on YORP effect + logical :: lgr = .false. + !! Turn on GR + logical :: lyarkovsky = .false. + !! Turn on Yarkovsky effect + logical :: lyorp = .false. + !! Turn on YORP effect contains procedure :: dealloc => base_util_dealloc_param procedure(abstract_io_dump_param), deferred :: dump @@ -140,43 +215,60 @@ module base subroutine abstract_io_dump_param(self, param_file_name) import base_parameters implicit none - class(base_parameters),intent(in) :: self !! Output collection of parameters - character(len=*), intent(in) :: param_file_name !! Parameter input file name (i.e. param.in) + class(base_parameters),intent(in) :: self + !! Output collection of parameters + character(len=*), intent(in) :: param_file_name + !! Parameter input file name (i.e. param.in) end subroutine abstract_io_dump_param subroutine abstract_io_param_reader(self, unit, iotype, v_list, iostat, iomsg) import base_parameters, I4B implicit none - class(base_parameters), intent(inout) :: self !! Collection of parameters - 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. - 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 + class(base_parameters), intent(inout) :: self + !! Collection of parameters + 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. + 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 abstract_io_param_reader subroutine abstract_io_param_writer(self, unit, iotype, v_list, iostat, iomsg) import base_parameters, I4B implicit none - class(base_parameters), intent(in) :: self !! Collection of parameters - 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(:) !! Not used in this procedure - integer(I4B), intent(out) :: iostat !! IO status code - character(len=*), intent(inout) :: iomsg !! Message to pass if iostat /= 0 + class(base_parameters), intent(in) :: self + !! Collection of parameters + 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(:) + !! Not used in this procedure + integer(I4B), intent(out) :: iostat + !! IO status code + character(len=*), intent(inout) :: iomsg + !! Message to pass if iostat /= 0 end subroutine abstract_io_param_writer subroutine abstract_io_read_in_param(self, param_file_name) import base_parameters implicit none - class(base_parameters), intent(inout) :: self !! Current run configuration parameters - character(len=*), intent(in) :: param_file_name !! Parameter input file name (i.e. param.in) + class(base_parameters), intent(inout) :: self + !! Current run configuration parameters + character(len=*), intent(in) :: param_file_name + !! Parameter input file name (i.e. param.in) end subroutine abstract_io_read_in_param end interface @@ -184,33 +276,47 @@ end subroutine abstract_io_read_in_param type :: base_storage_frame class(*), allocatable :: item contains - procedure :: store => base_util_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 :: base_final_storage_frame end type type, abstract :: base_storage - !! An class that establishes the pattern for various storage objects - 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(:), 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 + + !! An class that establishes the pattern for various storage objects + 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(:), 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 :: 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 + 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 @@ -230,7 +336,8 @@ end subroutine abstract_io_read_in_param subroutine abstract_util_dealloc_object(self) import base_object implicit none - class(base_object), intent(inout) :: self !! Generic Swiftest object type + class(base_object), intent(inout) :: self + !! Generic Swiftest object type end subroutine abstract_util_dealloc_object end interface @@ -307,17 +414,22 @@ end subroutine abstract_util_dealloc_object contains subroutine base_util_append_arr_char_string(arr, source, nold, lsource_mask) - !! author: David A. Minton - !! - !! Append a single array of character string type onto another. If the destination array is not allocated, or is not big - !! enough, this will allocate space for it. + + !! author: David A. Minton + !! + !! Append a single array of character string type onto another. If the destination array is not allocated, or is not big + !! enough, this will allocate space for it. implicit none ! Arguments - character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr !! Destination array - character(len=STRMAX), dimension(:), allocatable, intent(in) :: source !! Array to append - integer(I4B), intent(in), optional :: nold !! Extent of original array. If passed, the source array will begin at - !! arr(nold+1). Otherwise, the size of arr will be used. - logical, dimension(:), intent(in), optional :: lsource_mask !! Logical mask indicating which elements to append to + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + character(len=STRMAX), dimension(:), allocatable, intent(in) :: source + !! Array to append + integer(I4B), intent(in), optional :: nold + !! Extent of original array. If passed, the source array will begin at arr(nold+1). + !! Otherwise, the size of arr will be used. + logical, dimension(:), intent(in), optional :: lsource_mask + !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: nnew, nsrc, nend_orig @@ -354,17 +466,22 @@ end subroutine base_util_append_arr_char_string subroutine base_util_append_arr_DP(arr, source, nold, lsource_mask) - !! author: David A. Minton - !! - !! Append a single array of double precision type onto another. If the destination array is not allocated, or is not big - !! enough, this will allocate space for it. + !! author: David A. Minton + !! + !! Append a single array of double precision type onto another. If the destination array is not allocated, or is not big + !! enough, this will allocate space for it. implicit none ! Arguments - real(DP), dimension(:), allocatable, intent(inout) :: arr !! Destination array - real(DP), dimension(:), allocatable, intent(in) :: source !! Array to append - integer(I4B), intent(in), optional :: nold !! Extent of original array. If passed, the source array will begin at - !! arr(nold+1). Otherwise, the size of arr will be used. - logical, dimension(:), intent(in), optional :: lsource_mask !! Logical mask indicating which elements to append to + real(DP), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + real(DP), dimension(:), allocatable, intent(in) :: source + !! Array to append + integer(I4B), intent(in), optional :: nold + !! Extent of original array. If passed, the source array will begin at + + !! arr(nold+1). Otherwise, the size of arr will be used. + logical, dimension(:), intent(in), optional :: lsource_mask + !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: nnew, nsrc, nend_orig @@ -401,17 +518,21 @@ end subroutine base_util_append_arr_DP subroutine base_util_append_arr_DPvec(arr, source, nold, lsource_mask) - !! author: David A. Minton - !! - !! Append a single array of double precision vector type of size (NDIM, n) onto another. If the destination array is not - !! allocated, or is not big enough, this will allocate space for it. + !! author: David A. Minton + !! + !! Append a single array of double precision vector type of size (NDIM, n) onto another. If the destination array is not + !! allocated, or is not big enough, this will allocate space for it. implicit none ! Arguments - real(DP), dimension(:,:), allocatable, intent(inout) :: arr !! Destination array - real(DP), dimension(:,:), allocatable, intent(in) :: source !! Array to append - integer(I4B), intent(in), optional :: nold !! Extent of original array. If passed, the source array will begin at - !! arr(nold+1). Otherwise, the size of arr will be used. - logical, dimension(:), intent(in), optional :: lsource_mask !! Logical mask indicating which elements to append to + real(DP), dimension(:,:), allocatable, intent(inout) :: arr + !! Destination array + real(DP), dimension(:,:), allocatable, intent(in) :: source + !! Array to append + integer(I4B), intent(in), optional :: nold + !! Extent of original array. If passed, the source array will begin at arr(nold+1). + !! Otherwise, the size of arr will be used. + logical, dimension(:), intent(in), optional :: lsource_mask + !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: nnew, nsrc, nend_orig @@ -450,17 +571,21 @@ end subroutine base_util_append_arr_DPvec subroutine base_util_append_arr_I4B(arr, source, nold, lsource_mask) - !! author: David A. Minton - !! - !! Append a single array of integer(I4B) onto another. If the destination array is not allocated, or is not big enough, - !! this will allocate space for it. + !! author: David A. Minton + !! + !! Append a single array of integer(I4B) onto another. If the destination array is not allocated, or is not big enough, + !! this will allocate space for it. implicit none ! Arguments - integer(I4B), dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), allocatable, intent(in) :: source !! Array to append - integer(I4B), intent(in), optional :: nold !! Extent of original array. If passed, the source array will begin at - !! arr(nold+1). Otherwise, the size of arr will be used. - logical, dimension(:), intent(in), optional :: lsource_mask !! Logical mask indicating which elements to append to + integer(I4B), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I4B), dimension(:), allocatable, intent(in) :: source + !! Array to append + integer(I4B), intent(in), optional :: nold + !! Extent of original array. If passed, the source array will begin at arr(nold+1). + !! Otherwise, the size of arr will be used. + logical, dimension(:), intent(in), optional :: lsource_mask + !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: nnew, nsrc, nend_orig @@ -497,17 +622,21 @@ end subroutine base_util_append_arr_I4B subroutine base_util_append_arr_logical(arr, source, nold, lsource_mask) - !! author: David A. Minton - !! - !! Append a single array of logical type onto another. If the destination array is not allocated, or is not big enough, - !! this will allocate space for it. + !! author: David A. Minton + !! + !! Append a single array of logical type onto another. If the destination array is not allocated, or is not big enough, + !! this will allocate space for it. implicit none ! Arguments - logical, dimension(:), allocatable, intent(inout) :: arr !! Destination array - logical, dimension(:), allocatable, intent(in) :: source !! Array to append - integer(I4B), intent(in), optional :: nold !! Extent of original array. If passed, the source array will begin at - !! arr(nold+1). Otherwise, the size of arr will be used. - logical, dimension(:), intent(in), optional :: lsource_mask !! Logical mask indicating which elements to append to + logical, dimension(:), allocatable, intent(inout) :: arr + !! Destination array + logical, dimension(:), allocatable, intent(in) :: source + !! Array to append + integer(I4B), intent(in), optional :: nold + !! Extent of original array. If passed, the source array will begin at arr(nold+1). + !! Otherwise, the size of arr will be used. + logical, dimension(:), intent(in), optional :: lsource_mask + !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: nnew, nsrc, nend_orig @@ -544,12 +673,14 @@ end subroutine base_util_append_arr_logical 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. + !! author: David A. Minton + !! + !! Stores a snapshot of the nbody system so that later it can be retrieved for saving to file. implicit none - class(base_storage_frame), intent(inout) :: self !! Swiftest storage frame object - class(*), intent(in) :: source !! Swiftest n-body system object + class(base_storage_frame), intent(inout) :: self + !! Swiftest storage frame object + class(*), intent(in) :: source + !! Swiftest n-body system object if (allocated(self%item)) deallocate(self%item) allocate(self%item, source=source) @@ -559,12 +690,13 @@ end subroutine base_util_copy_store subroutine base_util_dealloc_param(self) - !! author: David A. Minton - !! - !! Deallocates all allocatables + !! author: David A. Minton + !! + !! Deallocates all allocatables implicit none ! Arguments - class(base_parameters),intent(inout) :: self !! Collection of parameters + class(base_parameters),intent(inout) :: self + !! Collection of parameters if (allocated(self%seed)) deallocate(self%seed) @@ -573,12 +705,13 @@ end subroutine base_util_dealloc_param 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 + !! 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 + class(base_storage), intent(inout) :: self + !! Swiftest storage object call self%reset() if (allocated(self%frame)) deallocate(self%frame) @@ -589,12 +722,12 @@ end subroutine base_util_dealloc_storage subroutine base_util_exit(code,unit) - !! author: David A. Minton - !! - !! Print termination message and exit program - !! - !! Adapted from David E. Kaufmann's Swifter routine: base_util_exit.f90 - !! Adapted from Hal Levison's Swift routine base_util_exit.f + !! author: David A. Minton + !! + !! Print termination message and exit program + !! + !! 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 @@ -602,7 +735,7 @@ subroutine base_util_exit(code,unit) ! Internals character(*), parameter :: BAR = '("---------------------------------------------------")' character(*), parameter :: SUCCESS_MSG = '(/, "Normal termination of Swiftest (version ", A, ")")' - character(*), parameter :: FAIL_MSG = '(/, "Terminating Swiftest (version ", A, ") due to error!!")' + character(*), parameter :: FAIL_MSG = '(/, "Terminating Swiftest (version ", A, ") due to error!")' character(*), parameter :: USAGE_MSG = '("Usage: swiftest_driver ' // & '[{standard}|compact|progress]")' character(*), parameter :: HELP_MSG = USAGE_MSG @@ -634,16 +767,20 @@ end subroutine base_util_exit subroutine base_util_fill_arr_char_string(keeps, inserts, lfill_list) - !! author: David A. Minton - !! - !! Performs a fill operation on a single array of type character strings - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a fill operation on a single array of type character strings. + !! This is the inverse of a spill operation implicit none ! Arguments - character(len=STRMAX), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - character(len=STRMAX), dimension(:), allocatable, intent(in) :: inserts !! Array of values to insert into keep - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the - !! keeps + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + character(len=STRMAX), dimension(:), allocatable, intent(in) :: inserts + !! Array of values to insert into keep + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the + + !! keeps if (.not.allocated(keeps) .or. .not.allocated(inserts)) return @@ -655,15 +792,18 @@ end subroutine base_util_fill_arr_char_string subroutine base_util_fill_arr_DP(keeps, inserts, lfill_list) - !! author: David A. Minton - !! - !! Performs a fill operation on a single array of type DP - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a fill operation on a single array of type DP. + !! This is the inverse of a spill operation implicit none ! Arguments - real(DP), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - real(DP), dimension(:), allocatable, intent(in) :: inserts !! Array of values to insert into keep - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + real(DP), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + real(DP), dimension(:), allocatable, intent(in) :: inserts + !! Array of values to insert into keep + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps if (.not.allocated(keeps) .or. .not.allocated(inserts)) return @@ -675,15 +815,18 @@ end subroutine base_util_fill_arr_DP subroutine base_util_fill_arr_DPvec(keeps, inserts, lfill_list) - !! author: David A. Minton - !! - !! Performs a fill operation on a single array of DP vectors with shape (NDIM, n) - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a fill operation on a single array of DP vectors with shape (NDIM, n) + !! This is the inverse of a spill operation implicit none ! Arguments - real(DP), dimension(:,:), allocatable, intent(inout) :: keeps !! Array of values to keep - real(DP), dimension(:,:), allocatable, intent(in) :: inserts !! Array of values to insert into keep - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + real(DP), dimension(:,:), allocatable, intent(inout) :: keeps + !! Array of values to keep + real(DP), dimension(:,:), allocatable, intent(in) :: inserts + !! Array of values to insert into keep + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps ! Internals integer(I4B) :: i @@ -699,15 +842,18 @@ end subroutine base_util_fill_arr_DPvec subroutine base_util_fill_arr_I4B(keeps, inserts, lfill_list) - !! author: David A. Minton - !! - !! Performs a fill operation on a single array of type I4B - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a fill operation on a single array of type I4B + !! This is the inverse of a spill operation implicit none ! Arguments - integer(I4B), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - integer(I4B), dimension(:), allocatable, intent(in) :: inserts !! Array of values to insert into keep - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + integer(I4B), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + integer(I4B), dimension(:), allocatable, intent(in) :: inserts + !! Array of values to insert into keep + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps if (.not.allocated(keeps) .or. .not.allocated(inserts)) return @@ -719,15 +865,18 @@ end subroutine base_util_fill_arr_I4B subroutine base_util_fill_arr_logical(keeps, inserts, lfill_list) - !! author: David A. Minton - !! - !! Performs a fill operation on a single array of logicals - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a fill operation on a single array of logicals + !! This is the inverse of a spill operation implicit none ! Arguments - logical, dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - logical, dimension(:), allocatable, intent(in) :: inserts !! Array of values to insert into keep - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + logical, dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + logical, dimension(:), allocatable, intent(in) :: inserts + !! Array of values to insert into keep + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps if (.not.allocated(keeps) .or. .not.allocated(inserts)) return @@ -738,10 +887,10 @@ subroutine base_util_fill_arr_logical(keeps, inserts, lfill_list) end subroutine base_util_fill_arr_logical 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 + !! 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 @@ -767,16 +916,20 @@ end subroutine base_util_reset_storage subroutine base_util_resize_arr_char_string(arr, nnew) - !! author: David A. Minton - !! - !! Resizes an array component of type character string. nnew = 0 will deallocate. + !! author: David A. Minton + !! + !! Resizes an array component of type character string. nnew = 0 will deallocate. implicit none ! Arguments - character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr !! Array to resize - integer(I4B), intent(in) :: nnew !! New size + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr + !! Array to resize + integer(I4B), intent(in) :: nnew + !! New size ! Internals - character(len=STRMAX), dimension(:), allocatable :: tmp !! Temp. storage array in case the input array is already allocated - integer(I4B) :: nold !! Old size + character(len=STRMAX), dimension(:), allocatable :: tmp + !! Temp. storage array in case the input array is already allocated + integer(I4B) :: nold + !! Old size if (nnew < 0) return @@ -811,16 +964,20 @@ end subroutine base_util_resize_arr_char_string subroutine base_util_resize_arr_DP(arr, nnew) - !! author: David A. Minton - !! - !! Resizes an array component of double precision type. Passing nnew = 0 will deallocate. + !! author: David A. Minton + !! + !! Resizes an array component of double precision type. Passing nnew = 0 will deallocate. implicit none ! Arguments - real(DP), dimension(:), allocatable, intent(inout) :: arr !! Array to resize - integer(I4B), intent(in) :: nnew !! New size + real(DP), dimension(:), allocatable, intent(inout) :: arr + !! Array to resize + integer(I4B), intent(in) :: nnew + !! New size ! Internals - real(DP), dimension(:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated - integer(I4B) :: nold !! Old size + real(DP), dimension(:), allocatable :: tmp + !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold + !! Old size real(DP), parameter :: init_val = 0.0_DP if (nnew < 0) return @@ -856,16 +1013,20 @@ end subroutine base_util_resize_arr_DP subroutine base_util_resize_arr_DPvec(arr, nnew) - !! author: David A. Minton - !! - !! Resizes an array component of double precision vectors of size (NDIM, n). Passing nnew = 0 will deallocate. + !! author: David A. Minton + !! + !! Resizes an array component of double precision vectors of size (NDIM, n). Passing nnew = 0 will deallocate. implicit none ! Arguments - real(DP), dimension(:,:), allocatable, intent(inout) :: arr !! Array to resize - integer(I4B), intent(in) :: nnew !! New size + real(DP), dimension(:,:), allocatable, intent(inout) :: arr + !! Array to resize + integer(I4B), intent(in) :: nnew + !! New size ! Internals - real(DP), dimension(:,:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated - integer(I4B) :: nold !! Old size + real(DP), dimension(:,:), allocatable :: tmp + !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold + !! Old size real(DP), dimension(NDIM), parameter :: init_val = 0.0_DP integer(I4B) :: i @@ -908,16 +1069,20 @@ end subroutine base_util_resize_arr_DPvec subroutine base_util_resize_arr_I4B(arr, nnew) - !! author: David A. Minton - !! - !! Resizes an array component of integer type. Passing nnew = 0 will deallocate. + !! author: David A. Minton + !! + !! Resizes an array component of integer type. Passing nnew = 0 will deallocate. implicit none ! Arguments - integer(I4B), dimension(:), allocatable, intent(inout) :: arr !! Array to resize - integer(I4B), intent(in) :: nnew !! New size + integer(I4B), dimension(:), allocatable, intent(inout) :: arr + !! Array to resize + integer(I4B), intent(in) :: nnew + !! New size ! Internals - integer(I4B), dimension(:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated - integer(I4B) :: nold !! Old size + integer(I4B), dimension(:), allocatable :: tmp + !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold + !! Old size integer(I4B), parameter :: init_val = -1 if (nnew < 0) return @@ -953,16 +1118,20 @@ end subroutine base_util_resize_arr_I4B subroutine base_util_resize_arr_logical(arr, nnew) - !! author: David A. Minton - !! - !! Resizes an array component of logical type. Passing nnew = 0 will deallocate. + !! author: David A. Minton + !! + !! Resizes an array component of logical type. Passing nnew = 0 will deallocate. implicit none ! Arguments - logical, dimension(:), allocatable, intent(inout) :: arr !! Array to resize - integer(I4B), intent(in) :: nnew !! New size + logical, dimension(:), allocatable, intent(inout) :: arr + !! Array to resize + integer(I4B), intent(in) :: nnew + !! New size ! Internals - logical, dimension(:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated - integer(I4B) :: nold !! Old size + logical, dimension(:), allocatable :: tmp + !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold + !! Old size logical, parameter :: init_val = .false. if (nnew < 0) return @@ -998,13 +1167,15 @@ end subroutine base_util_resize_arr_logical 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. + !! 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 + 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, nold, nbig @@ -1028,13 +1199,15 @@ 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. + !! 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 + 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)) @@ -1045,18 +1218,20 @@ 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. + !! 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 encounter storage object - class(*), intent(in) :: snapshot !! Object to snapshot + class(base_storage), intent(inout) :: self + !! Storage encounter storage object + class(*), intent(in) :: snapshot + !! Object to snapshot ! Internals integer(I4B) :: nnew, nold @@ -1076,22 +1251,24 @@ end subroutine base_util_snapshot_save subroutine base_util_spill_arr_char_string(keeps, discards, lspill_list, ldestructive) - !! author: David A. Minton - !! - !! Performs a spill operation on a single array of type character strings - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a spill operation on a single array of type character strings + !! This is the inverse of a spill operation implicit none ! Arguments - character(len=STRMAX), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - character(len=STRMAX), dimension(:), allocatable, intent(inout) :: discards !! Array of discards - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into - !! the discards - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not - !! this operation should alter the keeps - !! array or not + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: discards + !! Array of discards + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter the keeps array or not ! Internals integer(I4B) :: nspill, nkeep, nlist - character(len=STRMAX), dimension(:), allocatable :: tmp !! Array of values to keep + character(len=STRMAX), dimension(:), allocatable :: tmp + !! Array of values to keep nkeep = count(.not.lspill_list(:)) nspill = count(lspill_list(:)) @@ -1122,20 +1299,26 @@ end subroutine base_util_spill_arr_char_string subroutine base_util_spill_arr_DP(keeps, discards, lspill_list, ldestructive) - !! author: David A. Minton - !! - !! Performs a spill operation on a single array of type DP - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a spill operation on a single array of type DP + !! This is the inverse of a spill operation implicit none ! Arguments - real(DP), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - real(DP), dimension(:), allocatable, intent(inout) :: discards !! Array of discards - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discardss - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation - !! should alter the keeps array or not + real(DP), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + real(DP), dimension(:), allocatable, intent(inout) :: discards + !! Array of discards + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discardss + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation + + !! should alter the keeps array or not ! Internals integer(I4B) :: nspill, nkeep, nlist - real(DP), dimension(:), allocatable :: tmp !! Array of values to keep + real(DP), dimension(:), allocatable :: tmp + !! Array of values to keep nkeep = count(.not.lspill_list(:)) nspill = count(lspill_list(:)) @@ -1166,20 +1349,24 @@ end subroutine base_util_spill_arr_DP subroutine base_util_spill_arr_DPvec(keeps, discards, lspill_list, ldestructive) - !! author: David A. Minton - !! - !! Performs a spill operation on a single array of DP vectors with shape (NDIM, n) - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a spill operation on a single array of DP vectors with shape (NDIM, n) + !! This is the inverse of a spill operation implicit none ! Arguments - real(DP), dimension(:,:), allocatable, intent(inout) :: keeps !! Array of values to keep - real(DP), dimension(:,:), allocatable, intent(inout) :: discards !! Array discards - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this - !! operation should alter the keeps array or not + real(DP), dimension(:,:), allocatable, intent(inout) :: keeps + !! Array of values to keep + real(DP), dimension(:,:), allocatable, intent(inout) :: discards + !! Array discards + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter the keeps array or not ! Internals integer(I4B) :: i, nspill, nkeep, nlist - real(DP), dimension(:,:), allocatable :: tmp !! Array of values to keep + real(DP), dimension(:,:), allocatable :: tmp + !! Array of values to keep nkeep = count(.not.lspill_list(:)) nspill = count(lspill_list(:)) @@ -1214,20 +1401,24 @@ end subroutine base_util_spill_arr_DPvec subroutine base_util_spill_arr_I4B(keeps, discards, lspill_list, ldestructive) - !! author: David A. Minton - !! - !! Performs a spill operation on a single array of type I4B - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a spill operation on a single array of type I4B + !! This is the inverse of a spill operation implicit none ! Arguments - integer(I4B), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - integer(I4B), dimension(:), allocatable, intent(inout) :: discards !! Array of discards - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive!! Logical flag indicating whether or not this - !! operation should alter the keeps array or not + integer(I4B), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + integer(I4B), dimension(:), allocatable, intent(inout) :: discards + !! Array of discards + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter the keeps array or not ! Internals integer(I4B) :: nspill, nkeep, nlist - integer(I4B), dimension(:), allocatable :: tmp !! Array of values to keep + integer(I4B), dimension(:), allocatable :: tmp + !! Array of values to keep nkeep = count(.not.lspill_list(:)) nspill = count(lspill_list(:)) @@ -1258,20 +1449,26 @@ end subroutine base_util_spill_arr_I4B subroutine base_util_spill_arr_I8B(keeps, discards, lspill_list, ldestructive) - !! author: David A. Minton - !! - !! Performs a spill operation on a single array of type I4B - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a spill operation on a single array of type I4B + !! This is the inverse of a spill operation implicit none ! Arguments - integer(I8B), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - integer(I8B), dimension(:), allocatable, intent(inout) :: discards !! Array of discards - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive!! Logical flag indicating whether or not this - !! operation should alter the keeps array or not + integer(I8B), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + integer(I8B), dimension(:), allocatable, intent(inout) :: discards + !! Array of discards + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this + + !! operation should alter the keeps array or not ! Internals integer(I4B) :: nspill, nkeep, nlist - integer(I8B), dimension(:), allocatable :: tmp !! Array of values to keep + integer(I8B), dimension(:), allocatable :: tmp + !! Array of values to keep nkeep = count(.not.lspill_list(:)) nspill = count(lspill_list(:)) @@ -1302,20 +1499,26 @@ end subroutine base_util_spill_arr_I8B subroutine base_util_spill_arr_logical(keeps, discards, lspill_list, ldestructive) - !! author: David A. Minton - !! - !! Performs a spill operation on a single array of logicals - !! This is the inverse of a spill operation + !! author: David A. Minton + !! + !! Performs a spill operation on a single array of logicals + !! This is the inverse of a spill operation implicit none ! Arguments - logical, dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - logical, dimension(:), allocatable, intent(inout) :: discards !! Array of discards - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation - !! should alter the keeps array or no + logical, dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + logical, dimension(:), allocatable, intent(inout) :: discards + !! Array of discards + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation + + !! should alter the keeps array or no ! Internals integer(I4B) :: nspill, nkeep, nlist - logical, dimension(:), allocatable :: tmp !! Array of values to keep + logical, dimension(:), allocatable :: tmp + !! Array of values to keep nkeep = count(.not.lspill_list(:)) nspill = count(lspill_list(:)) @@ -1346,10 +1549,9 @@ end subroutine base_util_spill_arr_logical pure subroutine base_util_sort_dp(arr) - !! author: David A. Minton - !! - !! Sort input DP precision array in place into ascending numerical order using quicksort. - !! + !! author: David A. Minton + !! + !! Sort input DP precision array in place into ascending numerical order using quicksort. implicit none ! Arguments real(DP), dimension(:), intent(inout) :: arr @@ -1361,13 +1563,12 @@ end subroutine base_util_sort_dp pure subroutine base_util_sort_index_dp(arr, ind) - !! author: David A. Minton - !! - !! Sort input DP precision array by index in ascending numerical order using quick sort. - !! This algorithm works well for partially sorted arrays (which is usually the case here). - !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously - !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. - !! + !! author: David A. Minton + !! + !! Sort input DP precision array by index in ascending numerical order using quick sort. + !! This algorithm works well for partially sorted arrays (which is usually the case here). + !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously + !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. implicit none ! Arguments real(DP), dimension(:), intent(in) :: arr @@ -1390,15 +1591,15 @@ end subroutine base_util_sort_index_dp recursive pure subroutine base_util_sort_qsort_DP(arr, ind) - !! author: David A. Minton - !! - !! Sort input DP precision array by index in ascending numerical order using quicksort sort. - !! + !! author: David A. Minton + !! + !! Sort input DP precision array by index in ascending numerical order using quicksort sort. implicit none ! Arguments real(DP), dimension(:), intent(inout) :: arr integer(I4B),dimension(:),intent(out), optional :: ind - !! Internals + + !! Internals integer :: iq if (size(arr) > 1) then @@ -1418,10 +1619,10 @@ end subroutine base_util_sort_qsort_DP pure subroutine base_util_sort_partition_DP(arr, marker, ind) - !! author: David A. Minton - !! - !! Partition function for quicksort on DP type - !! + !! author: David A. Minton + !! + !! Partition function for quicksort on DP type + !! implicit none ! Arguments real(DP), intent(inout), dimension(:) :: arr @@ -1475,11 +1676,10 @@ end subroutine base_util_sort_partition_DP pure subroutine base_util_sort_i4b(arr) - !! author: David A. Minton - !! - !! Sort input integer array in place into ascending numerical order using quick sort. - !! This algorithm works well for partially sorted arrays (which is usually the case here) - !! + !! author: David A. Minton + !! + !! Sort input integer array in place into ascending numerical order using quick sort. + !! This algorithm works well for partially sorted arrays (which is usually the case here) implicit none ! Arguments integer(I4B), dimension(:), intent(inout) :: arr @@ -1491,12 +1691,11 @@ end subroutine base_util_sort_i4b pure subroutine base_util_sort_index_I4B(arr, ind) - !! author: David A. Minton - !! - !! Sort input integer array by index in ascending numerical order using quicksort. - !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously - !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. - !! + !! author: David A. Minton + !! + !! Sort input integer array by index in ascending numerical order using quicksort. + !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously + !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. implicit none ! Arguments integer(I4B), dimension(:), intent(in) :: arr @@ -1519,12 +1718,11 @@ end subroutine base_util_sort_index_I4B pure subroutine base_util_sort_index_I4B_I8Bind(arr, ind) - !! author: David A. Minton - !! - !! Sort input integer array by index in ascending numerical order using quicksort. - !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously - !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. - !! + !! author: David A. Minton + !! + !! Sort input integer array by index in ascending numerical order using quicksort. + !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously + !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. implicit none ! Arguments integer(I4B), dimension(:), intent(in) :: arr @@ -1547,12 +1745,11 @@ end subroutine base_util_sort_index_I4B_I8Bind pure subroutine base_util_sort_index_I8B_I8Bind(arr, ind) - !! author: David A. Minton - !! - !! Sort input integer array by index in ascending numerical order using quicksort. - !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously - !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. - !! + !! author: David A. Minton + !! + !! Sort input integer array by index in ascending numerical order using quicksort. + !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously + !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. implicit none ! Arguments integer(I8B), dimension(:), intent(in) :: arr @@ -1575,10 +1772,9 @@ end subroutine base_util_sort_index_I8B_I8Bind recursive pure subroutine base_util_sort_qsort_I4B(arr, ind) - !! author: David A. Minton - !! - !! Sort input I4B array by index in ascending numerical order using quicksort. - !! + !! author: David A. Minton + !! + !! Sort input I4B array by index in ascending numerical order using quicksort. implicit none ! Arguments integer(I4B), dimension(:), intent(inout) :: arr @@ -1603,10 +1799,10 @@ end subroutine base_util_sort_qsort_I4B recursive pure subroutine base_util_sort_qsort_I4B_I8Bind(arr, ind) - !! author: David A. Minton - !! - !! Sort input I4B array by index in ascending numerical order using quicksort. - !! + !! author: David A. Minton + !! + !! Sort input I4B array by index in ascending numerical order using quicksort. + !! implicit none ! Arguments integer(I4B), dimension(:), intent(inout) :: arr @@ -1631,10 +1827,9 @@ end subroutine base_util_sort_qsort_I4B_I8Bind recursive pure subroutine base_util_sort_qsort_I8B_I8Bind(arr, ind) - !! author: David A. Minton - !! - !! Sort input I8B array by index in ascending numerical order using quicksort. - !! + !! author: David A. Minton + !! + !! Sort input I8B array by index in ascending numerical order using quicksort. implicit none ! Arguments integer(I8B), dimension(:), intent(inout) :: arr @@ -1659,10 +1854,14 @@ end subroutine base_util_sort_qsort_I8B_I8Bind pure subroutine base_util_sort_partition_I4B(arr, marker, ind) - !! author: David A. Minton - !! - !! Partition function for quicksort on I4B type - !! + + !! author: David A. Minton + + !! + + !! Partition function for quicksort on I4B type + + !! implicit none ! Arguments integer(I4B), intent(inout), dimension(:) :: arr @@ -1716,10 +1915,9 @@ end subroutine base_util_sort_partition_I4B pure subroutine base_util_sort_partition_I4B_I8Bind(arr, marker, ind) - !! author: David A. Minton - !! - !! Partition function for quicksort on I4B type - !! + !! author: David A. Minton + !! + !! Partition function for quicksort on I4B type implicit none ! Arguments integer(I4B), intent(inout), dimension(:) :: arr @@ -1773,10 +1971,9 @@ end subroutine base_util_sort_partition_I4B_I8Bind pure subroutine base_util_sort_partition_I8B_I8Bind(arr, marker, ind) - !! author: David A. Minton - !! - !! Partition function for quicksort on I8B type with I8B index - !! + !! author: David A. Minton + !! + !! Partition function for quicksort on I8B type with I8B index implicit none ! Arguments integer(I8B), intent(inout), dimension(:) :: arr @@ -1830,10 +2027,10 @@ end subroutine base_util_sort_partition_I8B_I8Bind pure subroutine base_util_sort_sp(arr) - !! author: David A. Minton - !! - !! Sort input DP precision array in place into ascending numerical order using quicksort. - !! + !! author: David A. Minton + !! + !! Sort input DP precision array in place into ascending numerical order using quicksort. + !! implicit none ! Arguments real(SP), dimension(:), intent(inout) :: arr @@ -1845,12 +2042,11 @@ end subroutine base_util_sort_sp pure subroutine base_util_sort_index_sp(arr, ind) - !! author: David A. Minton - !! - !! Sort input DP precision array by index in ascending numerical order using quicksort. - !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously - !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. - !! + !! author: David A. Minton + !! + !! Sort input DP precision array by index in ascending numerical order using quicksort. + !! If ind is supplied already allocated, we assume it is an existing index array (e.g. a previously + !! sorted array). If it is not allocated, this subroutine swiftest_allocates it. implicit none ! Arguments real(SP), dimension(:), intent(in) :: arr @@ -1873,15 +2069,15 @@ end subroutine base_util_sort_index_sp recursive pure subroutine base_util_sort_qsort_SP(arr, ind) - !! author: David A. Minton - !! - !! Sort input DP precision array by index in ascending numerical order using quicksort. - !! + !! author: David A. Minton + !! + !! Sort input DP precision array by index in ascending numerical order using quicksort. implicit none ! Arguments real(SP), dimension(:), intent(inout) :: arr integer(I4B),dimension(:),intent(out), optional :: ind - !! Internals + + ! Internals integer :: iq if (size(arr) > 1) then @@ -1901,10 +2097,9 @@ end subroutine base_util_sort_qsort_SP pure subroutine base_util_sort_partition_SP(arr, marker, ind) - !! author: David A. Minton - !! - !! Partition function for quicksort on SP type - !! + !! author: David A. Minton + !! + !! Partition function for quicksort on SP type implicit none ! Arguments real(SP), intent(inout), dimension(:) :: arr @@ -1958,16 +2153,20 @@ end subroutine base_util_sort_partition_SP pure subroutine base_util_sort_rearrange_arr_char_string(arr, ind, n) - !! author: David A. Minton - !! - !! Rearrange a single array of character string in-place from an index list. + !! author: David A. Minton + !! + !! Rearrange a single array of character string in-place from an index list. implicit none ! Arguments - character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I4B), intent(in) :: n !! Number of elements in arr and ind to rearrange + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I4B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I4B), intent(in) :: n + !! Number of elements in arr and ind to rearrange ! Internals - character(len=STRMAX), dimension(:), allocatable :: tmp !! Temporary copy of arry used during rearrange operation + character(len=STRMAX), dimension(:), allocatable :: tmp + !! Temporary copy of arry used during rearrange operation if (.not. allocated(arr) .or. n <= 0) return allocate(tmp, mold=arr) @@ -1979,16 +2178,20 @@ end subroutine base_util_sort_rearrange_arr_char_string pure subroutine base_util_sort_rearrange_arr_DP(arr, ind, n) - !! author: David A. Minton - !! - !! Rearrange a single array of DP type in-place from an index list. + !! author: David A. Minton + !! + !! Rearrange a single array of DP type in-place from an index list. implicit none ! Arguments - real(DP), dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I4B), intent(in) :: n !! Number of elements in arr and ind to rearrange + real(DP), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I4B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I4B), intent(in) :: n + !! Number of elements in arr and ind to rearrange ! Internals - real(DP), dimension(:), allocatable :: tmp !! Temporary copy of array used during rearrange operation + real(DP), dimension(:), allocatable :: tmp + !! Temporary copy of array used during rearrange operation if (.not. allocated(arr) .or. n <= 0) return allocate(tmp, mold=arr) @@ -2000,16 +2203,20 @@ end subroutine base_util_sort_rearrange_arr_DP pure subroutine base_util_sort_rearrange_arr_DPvec(arr, ind, n) - !! author: David A. Minton - !! - !! Rearrange a single array of (NDIM,n) DP-type vectors in-place from an index list. + !! author: David A. Minton + !! + !! Rearrange a single array of (NDIM,n) DP-type vectors in-place from an index list. implicit none ! Arguments - real(DP), dimension(:,:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I4B), intent(in) :: n !! Number of elements in arr and ind to rearrange + real(DP), dimension(:,:), allocatable, intent(inout) :: arr + !! Destination array + integer(I4B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I4B), intent(in) :: n + !! Number of elements in arr and ind to rearrange ! Internals - real(DP), dimension(:,:), allocatable :: tmp !! Temporary copy of array used during rearrange operation + real(DP), dimension(:,:), allocatable :: tmp + !! Temporary copy of array used during rearrange operation if (.not. allocated(arr) .or. n <= 0) return allocate(tmp, mold=arr) @@ -2021,16 +2228,20 @@ end subroutine base_util_sort_rearrange_arr_DPvec pure subroutine base_util_sort_rearrange_arr_I4B(arr, ind, n) - !! author: David A. Minton - !! - !! Rearrange a single array of integers in-place from an index list. + !! author: David A. Minton + !! + !! Rearrange a single array of integers in-place from an index list. implicit none ! Arguments - integer(I4B), dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I4B), intent(in) :: n !! Number of elements in arr and ind to rearrange + integer(I4B), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I4B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I4B), intent(in) :: n + !! Number of elements in arr and ind to rearrange ! Internals - integer(I4B), dimension(:), allocatable :: tmp !! Temporary copy of array used during rearrange operation + integer(I4B), dimension(:), allocatable :: tmp + !! Temporary copy of array used during rearrange operation if (.not. allocated(arr) .or. n <= 0) return allocate(tmp, mold=arr) @@ -2041,16 +2252,20 @@ pure subroutine base_util_sort_rearrange_arr_I4B(arr, ind, n) end subroutine base_util_sort_rearrange_arr_I4B pure subroutine base_util_sort_rearrange_arr_I4B_I8Bind(arr, ind, n) - !! author: David A. Minton - !! - !! Rearrange a single array of integers in-place from an index list. + !! author: David A. Minton + !! + !! Rearrange a single array of integers in-place from an index list. implicit none ! Arguments - integer(I4B), dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I8B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I8B), intent(in) :: n !! Number of elements in arr and ind to rearrange + integer(I4B), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I8B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I8B), intent(in) :: n + !! Number of elements in arr and ind to rearrange ! Internals - integer(I4B), dimension(:), allocatable :: tmp !! Temporary copy of array used during rearrange operation + integer(I4B), dimension(:), allocatable :: tmp + !! Temporary copy of array used during rearrange operation if (.not. allocated(arr) .or. n <= 0_I8B) return allocate(tmp, mold=arr) @@ -2062,16 +2277,20 @@ end subroutine base_util_sort_rearrange_arr_I4B_I8Bind pure subroutine base_util_sort_rearrange_arr_logical_I8Bind(arr, ind, n) - !! author: David A. Minton - !! - !! Rearrange a single array of logicals in-place from an index list. + !! author: David A. Minton + !! + !! Rearrange a single array of logicals in-place from an index list. implicit none ! Arguments - logical, dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I8B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I8B), intent(in) :: n !! Number of elements in arr and ind to rearrange + logical, dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I8B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I8B), intent(in) :: n + !! Number of elements in arr and ind to rearrange ! Internals - logical, dimension(:), allocatable :: tmp !! Temporary copy of array used during rearrange operation + logical, dimension(:), allocatable :: tmp + !! Temporary copy of array used during rearrange operation if (.not. allocated(arr) .or. n <= 0) return allocate(tmp, mold=arr) @@ -2083,16 +2302,20 @@ end subroutine base_util_sort_rearrange_arr_logical_I8Bind pure subroutine base_util_sort_rearrange_arr_logical(arr, ind, n) - !! author: David A. Minton - !! - !! Rearrange a single array of logicals in-place from an index list. + !! author: David A. Minton + !! + !! Rearrange a single array of logicals in-place from an index list. implicit none ! Arguments - logical, dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I4B), intent(in) :: n !! Number of elements in arr and ind to rearrange + logical, dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I4B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I4B), intent(in) :: n + !! Number of elements in arr and ind to rearrange ! Internals - logical, dimension(:), allocatable :: tmp !! Temporary copy of array used during rearrange operation + logical, dimension(:), allocatable :: tmp + !! Temporary copy of array used during rearrange operation if (.not. allocated(arr) .or. n <= 0) return allocate(tmp, mold=arr) @@ -2104,16 +2327,18 @@ end subroutine base_util_sort_rearrange_arr_logical subroutine base_util_unique_DP(input_array, output_array, index_map) - !! author: David A. Minton - !! - !! Takes an input unsorted integer array and returns a new array of sorted, unique values (DP version) + !! author: David A. Minton + !! + !! Takes an input unsorted integer array and returns a new array of sorted, unique values (DP version) implicit none ! Arguments - real(DP), dimension(:), intent(in) :: input_array !! Unsorted input array - real(DP), dimension(:), allocatable, intent(out) :: output_array !! Sorted array of unique values - integer(I4B), dimension(:), allocatable, intent(out) :: index_map !! An array of the same size as input_array that such - !! that any for any index i, - !! output_array(index_map(i)) = input_array(i) + real(DP), dimension(:), intent(in) :: input_array + !! Unsorted input array + real(DP), dimension(:), allocatable, intent(out) :: output_array + !! Sorted array of unique values + integer(I4B), dimension(:), allocatable, intent(out) :: index_map + !! An array of the same size as input_array that such that any for any index i, + !! output_array(index_map(i)) = input_array(i) ! Internals real(DP), dimension(:), allocatable :: unique_array integer(I4B) :: n @@ -2139,16 +2364,18 @@ end subroutine base_util_unique_DP subroutine base_util_unique_I4B(input_array, output_array, index_map) - !! author: David A. Minton - !! + !! author: David A. Minton + !! !! Takes an input unsorted integer array and returns a new array of sorted, unique values (I4B version) implicit none ! Arguments - integer(I4B), dimension(:), intent(in) :: input_array !! Unsorted input array - integer(I4B), dimension(:), allocatable, intent(out) :: output_array !! Sorted array of unique values - integer(I4B), dimension(:), allocatable, intent(out) :: index_map !! An array of the same size as input_array that such - !! that any for any index i, - !! output_array(index_map(i)) = input_array(i) + integer(I4B), dimension(:), intent(in) :: input_array + !! Unsorted input array + integer(I4B), dimension(:), allocatable, intent(out) :: output_array + !! Sorted array of unique values + integer(I4B), dimension(:), allocatable, intent(out) :: index_map + !! An array of the same size as input_array that such that any for any index i, + !! output_array(index_map(i)) = input_array(i) ! Internals integer(I4B), dimension(:), allocatable :: unique_array integer(I4B) :: n, lo, hi @@ -2173,9 +2400,9 @@ end subroutine base_util_unique_I4B subroutine base_final_storage(self) - !! author: David A. Minton - !! - !! Finalizer for the storage object + !! author: David A. Minton + !! + !! Finalizer for the storage object implicit none ! Arguments class(base_storage), intent(inout) :: self @@ -2186,9 +2413,9 @@ end subroutine base_final_storage subroutine base_final_storage_frame(self) - !! author: David A. Minton - !! - !! Finalizer for the storage frame data type + !! author: David A. Minton + !! + !! Finalizer for the storage frame data type implicit none type(base_storage_frame) :: self @@ -2199,12 +2426,13 @@ end subroutine base_final_storage_frame #ifdef COARRAY subroutine base_coclone_param(self) - !! author: David A. Minton - !! - !! Broadcasts the image 1 parameter to all other images in a parameter coarray + !! author: David A. Minton + !! + !! Broadcasts the image 1 parameter to all other images in a parameter coarray implicit none ! Arguments - class(base_parameters),intent(inout),codimension[*] :: self !! Collection of parameters + class(base_parameters),intent(inout),codimension[*] :: self + !! Collection of parameters ! Internals call coclone(self%integrator) @@ -2261,7 +2489,7 @@ subroutine base_coclone_param(self) call coclone(self%lbig_discard) call coclone(self%lclose) call coclone(self%lenergy) - call coclone(self%loblatecb) + call coclone(self%lnon_spherical_cb) call coclone(self%lrotation) call coclone(self%ltides) call coclone(self%E_orbit_orig) diff --git a/src/helio/helio_kick.f90 b/src/helio/helio_kick.f90 index 0552d9168..7b7adee40 100644 --- a/src/helio/helio_kick.f90 +++ b/src/helio/helio_kick.f90 @@ -30,8 +30,8 @@ module subroutine helio_kick_getacch_pl(self, nbody_system, param, t, lbeg) associate(cb => nbody_system%cb, pl => self, npl => self%nbody) call pl%accel_int(param) - if (param%loblatecb) then - call pl%accel_obl(nbody_system) + if (param%lnon_spherical_cb) then + call pl%accel_non_spherical_cb(nbody_system) if (lbeg) then cb%aoblbeg = cb%aobl else @@ -74,12 +74,14 @@ module subroutine helio_kick_getacch_tp(self, nbody_system, param, t, lbeg) associate(tp => self, cb => nbody_system%cb, pl => nbody_system%pl, npl => nbody_system%pl%nbody) nbody_system%lbeg = lbeg - if (nbody_system%lbeg) then - call tp%accel_int(param, pl%Gmass(1:npl), pl%rbeg(:,1:npl), npl) - else - call tp%accel_int(param, pl%Gmass(1:npl), pl%rend(:,1:npl), npl) + if (npl > 0) then + if (nbody_system%lbeg) then + call tp%accel_int(param, pl%Gmass(1:npl), pl%rbeg(:,1:npl), npl) + else + call tp%accel_int(param, pl%Gmass(1:npl), pl%rend(:,1:npl), npl) + end if end if - if (param%loblatecb) call tp%accel_obl(nbody_system) + if (param%lnon_spherical_cb) call tp%accel_non_spherical_cb(nbody_system) if (param%lextra_force) call tp%accel_user(nbody_system, param, t, lbeg) if (param%lgr) call tp%accel_gr(param) end associate diff --git a/src/netcdf_io/netcdf_io_module.f90 b/src/netcdf_io/netcdf_io_module.f90 index c9d0df68e..2c072186f 100644 --- a/src/netcdf_io/netcdf_io_module.f90 +++ b/src/netcdf_io/netcdf_io_module.f90 @@ -291,6 +291,8 @@ module netcdf_io !! ID for the id of the other body involved in the discard logical :: lpseudo_vel_exists = .false. !! Logical flag to indicate whether or not the pseudovelocity vectors were present in an old file. + logical :: lc_lm_exists = .false. + !! Logical flag to indicate whether or not the c_lm array was present in an old file. contains procedure :: close => netcdf_io_close !! Closes an open NetCDF file diff --git a/src/rmvs/rmvs_kick.f90 b/src/rmvs/rmvs_kick.f90 index 3dd92ef60..b51b94737 100644 --- a/src/rmvs/rmvs_kick.f90 +++ b/src/rmvs/rmvs_kick.f90 @@ -52,8 +52,7 @@ module subroutine rmvs_kick_getacch_tp(self, nbody_system, param, t, lbeg) ! Temporarily turn off the heliocentric-dependent acceleration terms during an inner encounter using a copy of the parameter list with all of the heliocentric-specific acceleration terms turned off allocate(param_planetocen, source=param) - param_planetocen%loblatecb = .false. - param_planetocen%lshgrav = .false. + param_planetocen%lnon_spherical_cb = .false. param_planetocen%lextra_force = .false. param_planetocen%lgr = .false. @@ -91,7 +90,7 @@ module subroutine rmvs_kick_getacch_tp(self, nbody_system, param, t, lbeg) cb%Gmass = tp%cb_heliocentric%Gmass ! If the heliocentric-specifc acceleration terms are requested, compute those now - if (param%loblatecb) call tp%accel_obl(system_planetocen) + if (param%lnon_spherical_cb) call tp%accel_non_spherical_cb(system_planetocen) if (param%lextra_force) call tp%accel_user(system_planetocen, param, t, lbeg) if (param%lgr) call tp%accel_gr(param) diff --git a/src/rmvs/rmvs_step.f90 b/src/rmvs/rmvs_step.f90 index 04fadb74b..757ceb418 100644 --- a/src/rmvs/rmvs_step.f90 +++ b/src/rmvs/rmvs_step.f90 @@ -202,7 +202,7 @@ subroutine rmvs_step_out(cb, pl, tp, nbody_system, param, t, dt) call tp%step(nbody_system, param, outer_time, dto) tp%lfirst = lfirsttp else - if (param%loblatecb) then + if (param%lnon_spherical_cb) then call swiftest_obl_acc(npl, cb%Gmass, cb%j2rp2, cb%j4rp4, pl%rbeg, pl%lmask, pl%outer(outer_index-1)%aobl, cb%rot,& pl%Gmass, cb%aoblbeg) call swiftest_obl_acc(npl, cb%Gmass, cb%j2rp2, cb%j4rp4, pl%rend, pl%lmask, pl%outer(outer_index)%aobl, cb%rot, & @@ -267,14 +267,14 @@ subroutine rmvs_interp_in(cb, pl, nbody_system, param, dt, outer_index) xtmp(:, 1:npl) = pl%inner(0)%x(:, 1:npl) vtmp(:, 1:npl) = pl%inner(0)%v(:, 1:npl) - if ((param%loblatecb) .or. (param%ltides)) then + if ((param%lnon_spherical_cb) .or. (param%ltides)) then allocate(rh_original, source=pl%rh) allocate(ah_original, source=pl%ah) pl%rh(:, 1:npl) = xtmp(:, 1:npl) ! Temporarily replace heliocentric position with inner substep values to calculate the ! oblateness terms end if - if (param%loblatecb) then - call pl%accel_obl(nbody_system) + if (param%lnon_spherical_cb) then + call pl%accel_non_spherical_cb(nbody_system) pl%inner(0)%aobl(:, 1:npl) = pl%aobl(:, 1:npl) ! Save the oblateness acceleration on the planet for this substep end if ! TODO: Implement tides @@ -328,9 +328,9 @@ subroutine rmvs_interp_in(cb, pl, nbody_system, param, dt, outer_index) pl%inner(inner_index)%x(:, 1:npl) = pl%inner(inner_index)%x(:, 1:npl) + frac * xtmp(:, 1:npl) pl%inner(inner_index)%v(:, 1:npl) = pl%inner(inner_index)%v(:, 1:npl) + frac * vtmp(:, 1:npl) - if (param%loblatecb) then + if (param%lnon_spherical_cb) then pl%rh(:,1:npl) = pl%inner(inner_index)%x(:, 1:npl) - call pl%accel_obl(nbody_system) + call pl%accel_non_spherical_cb(nbody_system) pl%inner(inner_index)%aobl(:, 1:npl) = pl%aobl(:, 1:npl) end if ! TODO: Implement tides @@ -339,10 +339,10 @@ subroutine rmvs_interp_in(cb, pl, nbody_system, param, dt, outer_index) ! pl%inner(inner_index)%atide(:, 1:npl) = pl%atide(:, 1:npl) ! end if end do - if (param%loblatecb) then + if (param%lnon_spherical_cb) then ! Calculate the final value of oblateness accelerations at the final inner substep pl%rh(:, 1:npl) = pl%inner(NTPHENC)%x(:, 1:npl) - call pl%accel_obl(nbody_system) + call pl%accel_non_spherical_cb(nbody_system) pl%inner(NTPHENC)%aobl(:, 1:npl) = pl%aobl(:, 1:npl) end if ! TODO: Implement tides @@ -405,7 +405,7 @@ subroutine rmvs_step_in(cb, pl, tp, param, outer_time, dto) call plenci%set_beg_end(rbeg = plenci%inner(inner_index - 1)%x, & rend = plenci%inner(inner_index)%x) - if (param%loblatecb) then + if (param%lnon_spherical_cb) then cbenci%aoblbeg = cbenci%inner(inner_index - 1)%aobl(:, 1) cbenci%aoblend = cbenci%inner(inner_index )%aobl(:, 1) end if @@ -495,7 +495,7 @@ subroutine rmvs_make_planetocentric(param, cb, pl, tp) plenci%inner(inner_index)%x(:,1) = -cbenci%inner(inner_index)%x(:,1) plenci%inner(inner_index)%v(:,1) = -cbenci%inner(inner_index)%v(:,1) - if (param%loblatecb) then + if (param%lnon_spherical_cb) then allocate(plenci%inner(inner_index)%aobl, mold=pl%inner(inner_index)%aobl) allocate(cbenci%inner(inner_index)%aobl(NDIM,1)) cbenci%inner(inner_index)%aobl(:,1) = pl%inner(inner_index)%aobl(:, i) diff --git a/src/swiftest/swiftest_sph.f90 b/src/shgrav/shgrav_accel.f90 similarity index 50% rename from src/swiftest/swiftest_sph.f90 rename to src/shgrav/shgrav_accel.f90 index 3bdc1fceb..4dc29bbcb 100644 --- a/src/swiftest/swiftest_sph.f90 +++ b/src/shgrav/shgrav_accel.f90 @@ -10,41 +10,58 @@ !! Swiftest submodule to calculate higher order terms for gravitational acceleration given spherical harmonic coefficients (c_lm) -submodule (swiftest) s_swiftest_sph -use operators +submodule (shgrav) s_shgrav_accel +use swiftest use SHTOOLS contains - module subroutine swiftest_sph_g_acc_one(GMcb, r_0, phi_cb, rh, c_lm, g_sph, GMpl, aoblcb) + subroutine shgrav_g_acc_one(GMcb, r_0, phi_cb, rh, c_lm, g_sph, GMpl, aoblcb) !! author: Kaustub P. Anand !! !! Calculate the acceleration terms for one pair of bodies given c_lm, theta, phi, r - !! - implicit none ! Arguments - real(DP), intent(in) :: GMcb !! GMass of the central body - real(DP), intent(in) :: r_0 !! radius of the central body - real(DP), intent(in) :: phi_cb !! rotation phase angle of the central body - real(DP), intent(in), dimension(:) :: rh !! distance vector of body - real(DP), intent(in), dimension(:, :, :) :: c_lm !! Spherical Harmonic coefficients - real(DP), intent(out), dimension(NDIM) :: g_sph !! acceleration vector - real(DP), intent(in), optional :: GMpl !! Mass of input body if it is not a test particle - real(DP), dimension(:), intent(inout), optional :: aoblcb!! Barycentric acceleration of central body (only for massive input bodies) + real(DP), intent(in) :: GMcb + !! GMass of the central body + real(DP), intent(in) :: r_0 + !! radius of the central body + real(DP), intent(in) :: phi_cb + !! rotation phase angle of the central body + real(DP), intent(in), dimension(:) :: rh + !! distance vector of body + real(DP), intent(in), dimension(:, :, :) :: c_lm + !! Spherical Harmonic coefficients + real(DP), intent(out), dimension(NDIM) :: g_sph + !! acceleration vector + real(DP), intent(in), optional :: GMpl + !! Mass of input body if it is not a test particle + real(DP), dimension(:), intent(inout), optional :: aoblcb + !! Barycentric acceleration of central body (only for massive input bodies) ! Internals - integer :: l, m !! SPH coefficients - integer :: l_max !! max Spherical Harmonic l order value - integer(I4B) :: N, lmindex !! Length of Legendre polynomials and index at a given l, m - real(DP) :: r_mag !! magnitude of rh - real(DP) :: phi, phi_bar !! Azimuthal/Phase angle (radians) wrt coordinate axes, and central body rotation phase - real(DP) :: theta !! Inclination/Zenith angle (radians) - real(DP) :: plm, plm1 !! Associated Legendre polynomials at a given l, m - real(DP) :: ccss, cssc !! See definition in source code - real(DP) :: cos_theta, sin_theta !! cos(theta) and sin(theta) - real(DP), dimension(:), allocatable :: p !! Associated Lengendre Polynomials at a given cos(theta) - real(DP) :: fac1, fac2, r_fac !! calculation factors + integer :: l, m + !! SPH coefficients + integer :: l_max + !! max Spherical Harmonic l order value + integer(I4B) :: N, lmindex + !! Length of Legendre polynomials and index at a given l, m + real(DP) :: r_mag + !! magnitude of rh + real(DP) :: phi, phi_bar + !! Azimuthal/Phase angle (radians) wrt coordinate axes, and central body rotation phase + real(DP) :: theta + !! Inclination/Zenith angle (radians) + real(DP) :: plm, plm1 + !! Associated Legendre polynomials at a given l, m + real(DP) :: ccss, cssc + !! See definition in source code + real(DP) :: cos_theta, sin_theta + !! cos(theta) and sin(theta) + real(DP), dimension(:), allocatable :: p + !! Associated Lengendre Polynomials at a given cos(theta) + real(DP) :: fac1, fac2, r_fac + !! calculation factors g_sph(:) = 0.0_DP theta = atan2(sqrt(rh(1)**2 + rh(2)**2), rh(3)) @@ -117,70 +134,43 @@ module subroutine swiftest_sph_g_acc_one(GMcb, r_0, phi_cb, rh, c_lm, g_sph, GMp end if return - end subroutine swiftest_sph_g_acc_one + end subroutine shgrav_g_acc_one - module subroutine swiftest_sph_g_acc_pl_all(self, nbody_system) + module subroutine shgrav_acc(body, nbody_system) !! author: Kaustub P. Anand !! - !! Calculate the acceleration terms for all massive bodies given c_lm + !! Calculate the acceleration terms for bodies given c_lm values for the central body !! implicit none ! Arguments - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object + class(swiftest_body), intent(inout) :: body + !! Swiftest body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object ! Internals - integer(I4B) :: i = 1 - real(DP), dimension(NDIM) :: g_sph !! Gravitational terms from Spherical Harmonics + integer(I4B) :: i + real(DP), dimension(NDIM) :: g_sph + !! Gravitational terms from Spherical Harmonics - associate(pl => self, npl => self%nbody, cb => nbody_system%cb, rh => self%rh) + associate(cb => nbody_system%cb) cb%aobl(:) = 0.0_DP - - do i = 1, npl - if (pl%lmask(i)) then - ! theta = atan2(sqrt(rh(1,i)**2 + rh(2,i)**2), rh(3,i)) - ! phi = atan2(rh(2,i), rh(1,i)) ! - cb%rotphase - - call swiftest_sph_g_acc_one(cb%Gmass, cb%radius, cb%rotphase, rh(:,i), cb%c_lm, g_sph, pl%Gmass(i), cb%aobl) - pl%ah(:, i) = pl%ah(:, i) + g_sph(:) - cb%aobl(:) - pl%aobl(:, i) = g_sph(:) - end if - end do + select type(body) + class is (swiftest_pl) + do i = 1, body%nbody + if (body%lmask(i)) then + call shgrav_g_acc_one(cb%Gmass, cb%radius, cb%rotphase, body%rh(:,i), cb%c_lm, body%aobl(:,i), & + GMpl=body%Gmass(i), aoblcb=cb%aobl) + end if + end do + class is (swiftest_tp) + do i = 1, body%nbody + if (body%lmask(i)) then + call shgrav_g_acc_one(cb%Gmass, cb%radius, cb%rotphase, body%rh(:,i), cb%c_lm, body%aobl(:,i)) + end if + end do + end select end associate return - end subroutine swiftest_sph_g_acc_pl_all - - module subroutine swiftest_sph_g_acc_tp_all(self, nbody_system) - !! author: Kaustub P. Anand - !! - !! Calculate the acceleration terms for all test particles given c_lm - !! - implicit none - ! Arguments - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - ! Internals - integer(I4B) :: i = 1 - real(DP), dimension(NDIM) :: g_sph !! Gravitational terms from Spherical Harmonics - real(DP), dimension(NDIM) :: aoblcb !! Temporary variable for central body oblateness acceleration - - associate(tp => self, ntp => self%nbody, cb => nbody_system%cb, rh => self%rh) - - if (nbody_system%lbeg) then - aoblcb = cb%aoblbeg - else - aoblcb = cb%aoblend - end if - - do i = 1, ntp - if (tp%lmask(i)) then - - call swiftest_sph_g_acc_one(cb%Gmass, cb%radius, cb%rotphase, rh(:,i), cb%c_lm, g_sph) - tp%ah(:, i) = tp%ah(:, i) + g_sph(:) - aoblcb(:) - tp%aobl(:, i) = g_sph(:) - end if - end do - end associate - return - end subroutine swiftest_sph_g_acc_tp_all + end subroutine shgrav_acc -end submodule s_swiftest_sph \ No newline at end of file +end submodule s_shgrav_accel \ No newline at end of file diff --git a/src/shgrav/shgrav_module.f90 b/src/shgrav/shgrav_module.f90 index 0007bb2af..416f51d19 100644 --- a/src/shgrav/shgrav_module.f90 +++ b/src/shgrav/shgrav_module.f90 @@ -16,5 +16,16 @@ module shgrav implicit none public + interface + module subroutine shgrav_acc(body, nbody_system) + implicit none + class(swiftest_body), intent(inout) :: body + !! Swiftest body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + end subroutine shgrav_acc + + end interface + end module shgrav \ No newline at end of file diff --git a/src/swiftest/swiftest_coarray.f90 b/src/swiftest/swiftest_coarray.f90 index c8e4da943..60912902f 100644 --- a/src/swiftest/swiftest_coarray.f90 +++ b/src/swiftest/swiftest_coarray.f90 @@ -239,6 +239,7 @@ module subroutine swiftest_coarray_coclone_nc(self) call coclone(self%discard_vh_varid) call coclone(self%discard_body_id_varname) call coclone(self%lpseudo_vel_exists) + call coclone(self%lc_lm_exists) return end subroutine swiftest_coarray_coclone_nc diff --git a/src/swiftest/swiftest_discard.f90 b/src/swiftest/swiftest_discard.f90 index e9a19e374..33dd7feb0 100644 --- a/src/swiftest/swiftest_discard.f90 +++ b/src/swiftest/swiftest_discard.f90 @@ -27,8 +27,8 @@ module subroutine swiftest_discard_system(self, param) class(swiftest_pl), allocatable :: plsub class(swiftest_tp), allocatable :: tpsub - lpl_check = allocated(self%pl_discards) - ltp_check = allocated(self%tp_discards) + lpl_check = allocated(self%pl_discards) .and. self%pl%nbody > 0 + ltp_check = allocated(self%tp_discards) .and. self%tp%nbody > 0 associate(nbody_system => self,tp => self%tp,pl => self%pl,tp_discards => self%tp_discards,pl_discards => self%pl_discards, & npl => self%pl%nbody, ntp => self%tp%nbody, t => self%t, collision_history => self%collision_history, & @@ -38,19 +38,29 @@ module subroutine swiftest_discard_system(self, param) if (lpl_check .and. pl%nbody > 0) then pl%ldiscard = pl%status(:) /= ACTIVE call pl%discard(nbody_system, param) - lpl_discards = any(pl%ldiscard(1:npl)) + if (npl > 0) lpl_discards = any(pl%ldiscard(1:npl)) end if if (ltp_check .and. tp%nbody > 0) then tp%ldiscard = tp%status(:) /= ACTIVE call tp%discard(nbody_system, param) - ltp_discards = any(tp%ldiscard(1:ntp)) - lpl_discards = any(pl%ldiscard(1:npl)) + if (ntp > 0) ltp_discards = any(tp%ldiscard(1:ntp)) + if (npl > 0) lpl_discards = any(pl%ldiscard(1:npl)) end if if (ltp_discards.or.lpl_discards) then + ! Advance the collision id number and save it + collider%maxid_collision = collider%maxid_collision + 1 + collider%collision_id = collider%maxid_collision + collider%impactors%regime = COLLRESOLVE_REGIME_MERGE + write(idstr,*) collider%collision_id + call swiftest_io_log_one_message(COLLISION_LOG_OUT, "collision_id " // trim(adjustl(idstr))) + if (ltp_discards) then allocate(ldiscard, source=tp%ldiscard(:)) + do i = 1, ntp + if (ldiscard(i)) call tp%info(i)%set_value(collision_id=collider%collision_id) + end do allocate(tpsub, mold=tp) call tp%spill(tpsub, ldiscard, ldestructive=.true.) nsub = tpsub%nbody @@ -70,6 +80,9 @@ module subroutine swiftest_discard_system(self, param) ! simply used to trigger a snapshot. if (param%lenergy) call self%conservation_report(param, lterminal=.false.) allocate(ldiscard, source=pl%ldiscard(:)) + do i = 1, npl + if (ldiscard(i)) call pl%info(i)%set_value(collision_id=collider%collision_id) + end do allocate(plsub, mold=pl) call pl%spill(plsub, ldiscard, ldestructive=.false.) nsub = plsub%nbody @@ -86,13 +99,7 @@ module subroutine swiftest_discard_system(self, param) end select call pl_discards%setup(0,param) end if - ! Advance the collision id number and save it - collider%maxid_collision = max(collider%maxid_collision, maxval(nbody_system%pl%info(:)%collision_id)) - collider%maxid_collision = collider%maxid_collision + 1 - collider%collision_id = collider%maxid_collision - collider%impactors%regime = COLLRESOLVE_REGIME_MERGE - write(idstr,*) collider%collision_id - call swiftest_io_log_one_message(COLLISION_LOG_OUT, "collision_id " // trim(adjustl(idstr))) + call collision_history%take_snapshot(param,nbody_system, t, "particle") end if diff --git a/src/swiftest/swiftest_io.f90 b/src/swiftest/swiftest_io.f90 index 685954b0d..c50345cd3 100644 --- a/src/swiftest/swiftest_io.f90 +++ b/src/swiftest/swiftest_io.f90 @@ -168,16 +168,19 @@ module subroutine swiftest_io_conservation_report(self, param, lterminal) end if if (.not.param%lfirstenergy) then - - nbody_system%ke_orbit_error = (ke_orbit_now - nbody_system%ke_orbit_orig) / abs(nbody_system%E_orbit_orig) - nbody_system%ke_spin_error = (ke_spin_now - nbody_system%ke_spin_orig) / abs(nbody_system%E_orbit_orig) - nbody_system%pe_error = (pe_now - nbody_system%pe_orig) / abs(nbody_system%E_orbit_orig) + nbody_system%ke_orbit_error = (ke_orbit_now - nbody_system%ke_orbit_orig) / abs(nbody_system%te_orig) + nbody_system%ke_spin_error = (ke_spin_now - nbody_system%ke_spin_orig) / abs(nbody_system%te_orig) + nbody_system%pe_error = (pe_now - nbody_system%pe_orig) / abs(nbody_system%te_orig) be_cb_orig = -(3 * cb%GM0**2 / param%GU) / (5 * cb%R0) nbody_system%be_error = (be_now - nbody_system%be_orig) / abs(nbody_system%te_orig) + (be_cb_now - be_cb_orig) & / abs(nbody_system%te_orig) - nbody_system%E_orbit_error = (E_orbit_now - nbody_system%E_orbit_orig) / abs(nbody_system%E_orbit_orig) + if (abs(nbody_system%E_orbit_orig) < 10*tiny(1.0_DP)) then + nbody_system%E_orbit_error = 0.0_DP + else + nbody_system%E_orbit_error = (E_orbit_now - nbody_system%E_orbit_orig) / abs(nbody_system%E_orbit_orig) + end if nbody_system%Ecoll_error = nbody_system%E_collisions / abs(nbody_system%te_orig) nbody_system%E_untracked_error = nbody_system%E_untracked / abs(nbody_system%te_orig) nbody_system%te_error = (nbody_system%te - nbody_system%te_orig - nbody_system%E_collisions - nbody_system%E_untracked)& @@ -880,7 +883,7 @@ module subroutine swiftest_io_netcdf_initialize_output(self, param) nc%vh_varid), "netcdf_io_initialize_output nf90_def_var vh_varid" ) !! When GR is enabled, we need to save the pseudovelocity vectors in addition to the true heliocentric velocity vectors, - !! otherwise !! we cannnot expect bit-identical runs from restarted runs with GR enabled due to floating point errors + !! otherwise we cannnot expect bit-identical runs from restarted runs with GR enabled due to floating point errors !! during the conversion. if (param%lgr) then call netcdf_io_check( nf90_def_var(nc%id, nc%gr_pseudo_vh_varname, nc%out_type, & @@ -1008,11 +1011,10 @@ module subroutine swiftest_io_netcdf_initialize_output(self, param) call netcdf_io_check( nf90_def_var(nc%id, nc%j4rp4_varname, nc%out_type, nc%time_dimid, nc%j4rp4_varid), & "netcdf_io_initialize_output nf90_def_var j4rp4_varid" ) - ! status = nf90_inq_varid(nc%id, nc%c_lm_varname, nc%c_lm_varid) - ! if (status == NF90_NOERR) then - call netcdf_io_check( nf90_def_var(nc%id, nc%c_lm_varname, nc%out_type, [nc%m_dimid, nc%l_dimid, nc%sign_dimid], & + if (nc%lc_lm_exists) then + call netcdf_io_check( nf90_def_var(nc%id, nc%c_lm_varname, nc%out_type, [nc%m_dimid, nc%l_dimid, nc%sign_dimid], & nc%c_lm_varid), "netcdf_io_initialize_output nf90_def_var c_lm_varid" ) - ! end if + end if ! Set fill mode to NaN for all variables call netcdf_io_check( nf90_inquire(nc%id, nVariables=nvar), "netcdf_io_initialize_output nf90_inquire nVariables" ) @@ -1576,6 +1578,10 @@ module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ier call netcdf_io_check( nf90_get_var(nc%id, nc%c_lm_varid, cb%c_lm, count = [m_dim_max, l_dim_max, 2]), "netcdf_io_read_frame_system nf90_getvar c_lm_varid") ! ordering of dimensions above seen to stackoverflow to prevent error 'NetCDF: Start + count exceeds dimension bound' + nc%lc_lm_exists = .true. + else + if (allocated(cb%c_lm)) deallocate(cb%c_lm) + nc%lc_lm_exists = .false. end if call self%read_particle_info(nc, param, plmask, tpmask) @@ -3370,10 +3376,8 @@ module subroutine swiftest_io_read_in_system(self, nc, param) if (ierr /=0) call base_util_exit(FAILURE,param%display_unit) end if - param%lshgrav = allocated(self%cb%c_lm) - - param%loblatecb = ((self%cb%j2rp2 /= 0.0_DP) .or. (self%cb%j4rp4 /= 0.0_DP)) .and. (.not. param%lshgrav) - if (.not.param%loblatecb .and. .not.param%lshgrav) then + param%lnon_spherical_cb = (self%cb%j2rp2 /= 0.0_DP) .or. (self%cb%j4rp4 /= 0.0_DP) .or. allocated(self%cb%c_lm) + if (.not.param%lnon_spherical_cb) then if (allocated(self%pl%aobl)) deallocate(self%pl%aobl) if (allocated(self%tp%aobl)) deallocate(self%tp%aobl) else diff --git a/src/swiftest/swiftest_module.f90 b/src/swiftest/swiftest_module.f90 index e513623b7..0e0c40749 100644 --- a/src/swiftest/swiftest_module.f90 +++ b/src/swiftest/swiftest_module.f90 @@ -36,7 +36,7 @@ module swiftest !! construct in order to "reveal" the procedures. This is done throughout the project at the beginning of many procedures (along !! with copious amounts of associate(...) statements, in order to help with code readibility) !! - !! Adapted from David E. Kaufmann's Swifter routine: module_swifter.f90 + !! Adapted from David E. Kaufmann's Swifter routine: module_swifter.f90 use globals use operators use lambda_function @@ -47,7 +47,6 @@ module swiftest use io_progress_bar use netcdf_io use solver - use SHTOOLS #ifdef COARRAY use coarray #endif @@ -58,13 +57,14 @@ module swiftest type, extends(netcdf_parameters) :: swiftest_netcdf_parameters contains - procedure :: initialize => swiftest_io_netcdf_initialize_output !! Initialize a set of parameters used to identify a - !! NetCDF output object - procedure :: get_valid_masks => swiftest_io_netcdf_get_valid_masks !! Gets logical masks indicating which bodies are valid - !! pl and tp type at the current time - procedure :: open => swiftest_io_netcdf_open !! Opens a NetCDF file and does the variable inquiries to - !! activate variable ids - procedure :: flush => swiftest_io_netcdf_flush !! Flushes a NetCDF file by closing it then opening it again + procedure :: initialize => swiftest_io_netcdf_initialize_output + !! Initialize a set of parameters used to identify a NetCDF output object + procedure :: get_valid_masks => swiftest_io_netcdf_get_valid_masks + !! Gets logical masks indicating which bodies are valid pl and tp type at the current time + procedure :: open => swiftest_io_netcdf_open + !! Opens a NetCDF file and does the variable inquiries to activate variable ids + procedure :: flush => swiftest_io_netcdf_flush + !! Flushes a NetCDF file by closing it then opening it again #ifdef COARRAY procedure :: coclone => swiftest_coarray_coclone_nc #endif @@ -72,16 +72,19 @@ module swiftest type, extends(base_storage) :: swiftest_storage - class(swiftest_netcdf_parameters), allocatable :: nc !! NetCDF object attached to this storage object + class(swiftest_netcdf_parameters), allocatable :: nc + !! NetCDF object attached to this storage object contains - procedure :: dump => swiftest_io_dump_storage !! Dumps storage object contents to file - procedure :: dealloc => swiftest_util_dealloc_storage !! Resets a storage object by deallocating all items and - !! resetting the frame counter to 0 - procedure :: get_index_values => swiftest_util_get_vals_storage !! Gets the unique values of the indices of a storage object - !! (i.e. body id or time value) - procedure :: make_index_map => swiftest_util_index_map_storage !! Maps body id values to storage index values so we don't - !! have to use unlimited dimensions for id - procedure :: take_snapshot => swiftest_util_snapshot_system !! Takes a snapshot of the nbody_system for later file storage + procedure :: dump => swiftest_io_dump_storage + !! Dumps storage object contents to file + procedure :: dealloc => swiftest_util_dealloc_storage + !! Resets a storage object by deallocating all items and resetting the frame counter to 0 + procedure :: get_index_values => swiftest_util_get_vals_storage + !! Gets the unique values of the indices of a storage object (i.e. body id or time value) + procedure :: make_index_map => swiftest_util_index_map_storage + !! Maps body id values to storage index values so we don't have to use unlimited dimensions for id + procedure :: take_snapshot => swiftest_util_snapshot_system + !! Takes a snapshot of the nbody_system for later file storage final :: swiftest_final_storage end type swiftest_storage @@ -100,76 +103,118 @@ module swiftest !> Class definition for the kinship relationships used in bookkeeping multiple collisions bodies in a single time step. type, extends(base_kinship) :: swiftest_kinship - integer(I4B) :: parent !! Index of parent particle - integer(I4B) :: nchild !! number of children in merger list - integer(I4B), dimension(:), allocatable :: child !! Index of children particles + integer(I4B) :: parent + !! Index of parent particle + integer(I4B) :: nchild + !! number of children in merger list + integer(I4B), dimension(:), allocatable :: child + !! Index of children particles contains - procedure :: dealloc => swiftest_util_dealloc_kin !! Deallocates all allocatable arrays + procedure :: dealloc => swiftest_util_dealloc_kin + !! Deallocates all allocatable arrays #ifdef COARRAY - procedure :: coclone => swiftest_coarray_coclone_kin !! Clones the image 1 body object to all other images in the coarray - !! structure. + procedure :: coclone => swiftest_coarray_coclone_kin + !! Clones the image 1 body object to all other images in the coarray structure. #endif - final :: swiftest_final_kin !! Finalizes the Swiftest kinship object - deallocates all allocatables + final :: swiftest_final_kin + !! Finalizes the Swiftest kinship object - deallocates all allocatables end type swiftest_kinship type, extends(base_particle_info) :: swiftest_particle_info - character(len=NAMELEN) :: name !! Non-unique name - character(len=NAMELEN) :: particle_type !! String containing a description of the particle type (e.g. Central Body, - !! Massive Body, Test Particle) - character(len=NAMELEN) :: origin_type !! String containing a description of the origin of the particle (e.g. Initial - !! Conditions, Supercatastrophic, Disruption, etc.) - real(DP) :: origin_time !! The time of the particle's formation - integer(I4B) :: collision_id !! The ID of the collision that formed the particle - real(DP), dimension(NDIM) :: origin_rh !! The heliocentric distance vector at the time of the particle's formation - real(DP), dimension(NDIM) :: origin_vh !! The heliocentric velocity vector at the time of the particle's formation - real(DP) :: discard_time !! The time of the particle's discard - character(len=NAMELEN) :: status !! Particle status description: Active, Merged, Fragmented, etc. - real(DP), dimension(NDIM) :: discard_rh !! The heliocentric distance vector at the time of the particle's discard - real(DP), dimension(NDIM) :: discard_vh !! The heliocentric velocity vector at the time of the particle's discard - integer(I4B) :: discard_body_id !! The id of the other body involved in the discard (0 if no other body involved) + character(len=NAMELEN) :: name + !! Non-unique name + character(len=NAMELEN) :: particle_type + !! String containing a description of the particle type (e.g. Central Body, Massive Body, Test Particle) + character(len=NAMELEN) :: origin_type + !! String containing a description of the origin of the particle (e.g. Initial Conditions, Disruption, etc.) + real(DP) :: origin_time + !! The time of the particle's formation + integer(I4B) :: collision_id + !! The ID of the collision that formed the particle + real(DP), dimension(NDIM) :: origin_rh + !! The heliocentric distance vector at the time of the particle's formation + real(DP), dimension(NDIM) :: origin_vh + !! The heliocentric velocity vector at the time of the particle's formation + real(DP) :: discard_time + !! The time of the particle's discard + character(len=NAMELEN) :: status + !! Particle status description: Active, Merged, Fragmented, etc. + real(DP), dimension(NDIM) :: discard_rh + !! The heliocentric distance vector at the time of the particle's discard + real(DP), dimension(NDIM) :: discard_vh + !! The heliocentric velocity vector at the time of the particle's discard + integer(I4B) :: discard_body_id + !! The id of the other body involved in the discard (0 if no other body involved) contains - procedure :: copy => swiftest_util_copy_particle_info !! Copies one set of information object components into another, - !! component-by-component - procedure :: set_value => swiftest_util_set_particle_info !! Sets one or more values of the particle information metadata - !! object + procedure :: copy => swiftest_util_copy_particle_info + !! Copies one set of information object components into another, component-by-component + procedure :: set_value => swiftest_util_set_particle_info + !! Sets one or more values of the particle information metadata object end type swiftest_particle_info !> An abstract class for a generic collection of Swiftest bodies type, abstract, extends(base_object) :: swiftest_body - !! Superclass that defines the generic elements of a Swiftest particle - logical :: lfirst = .true. !! Run the current step as a first - integer(I4B) :: nbody = 0 !! Number of bodies - integer(I4B), dimension(:), allocatable :: id !! Identifier - type(swiftest_particle_info), dimension(:), allocatable :: info !! Particle metadata information - logical, dimension(:), allocatable :: lmask !! Logical mask used to select a subset of bodies when performing certain operations (drift, kick, accel, etc.) - integer(I4B), dimension(:), allocatable :: status !! An integrator-specific status indicator - logical, dimension(:), allocatable :: ldiscard !! Body should be discarded - logical, dimension(:), allocatable :: lcollision !! flag indicating whether body has merged with another this time step - logical, dimension(:), allocatable :: lencounter !! flag indicating whether body is part of an encounter this time step - real(DP), dimension(:), allocatable :: mu !! G * (Mcb + [m]) - real(DP), dimension(:,:), allocatable :: rh !! Heliocentric position - real(DP), dimension(:,:), allocatable :: vh !! Heliocentric velocity - real(DP), dimension(:,:), allocatable :: rb !! Barycentric position - real(DP), dimension(:,:), allocatable :: vb !! Barycentric velocity - real(DP), dimension(:,:), allocatable :: ah !! Total heliocentric acceleration - real(DP), dimension(:,:), allocatable :: aobl !! Barycentric accelerations of bodies due to central body oblatenes - real(DP), dimension(:,:), allocatable :: agr !! Acceleration due to post-Newtonian correction - real(DP), dimension(:,:), allocatable :: atide !! Tanngential component of acceleration of bodies due to tides - real(DP), dimension(:), allocatable :: ir3h !! Inverse heliocentric radius term (1/rh**3) - integer(I4B), dimension(:), allocatable :: isperi !! perihelion passage flag - real(DP), dimension(:), allocatable :: peri !! perihelion distance - real(DP), dimension(:), allocatable :: atp !! semimajor axis following perihelion passage - real(DP), dimension(:), allocatable :: a !! Semimajor axis (pericentric distance for a parabolic orbit) - real(DP), dimension(:), allocatable :: e !! Eccentricity - real(DP), dimension(:), allocatable :: inc !! Inclination - real(DP), dimension(:), allocatable :: capom !! Longitude of ascending node - real(DP), dimension(:), allocatable :: omega !! Argument of pericenter - real(DP), dimension(:), allocatable :: capm !! Mean anomaly - - !! Note to developers: If you add components to this class, be sure to update methods and subroutines that traverse the - !! component list, such as setup_body and util_spill + !! Superclass that defines the generic elements of a Swiftest particle + logical :: lfirst = .true. + !! Run the current step as a first + integer(I4B) :: nbody = 0 + !! Number of bodies + integer(I4B), dimension(:), allocatable :: id + !! Identifier + type(swiftest_particle_info), dimension(:), allocatable :: info + !! Particle metadata information + logical, dimension(:), allocatable :: lmask + !! Logical mask used to select a subset of bodies when performing certain operations (drift, kick, accel, etc.) + integer(I4B), dimension(:), allocatable :: status + !! An integrator-specific status indicator + logical, dimension(:), allocatable :: ldiscard + !! Body should be discarded + logical, dimension(:), allocatable :: lcollision + !! flag indicating whether body has merged with another this time step + logical, dimension(:), allocatable :: lencounter + !! flag indicating whether body is part of an encounter this time step + real(DP), dimension(:), allocatable :: mu + !! G * (Mcb + [m]) + real(DP), dimension(:,:), allocatable :: rh + !! Heliocentric position + real(DP), dimension(:,:), allocatable :: vh + !! Heliocentric velocity + real(DP), dimension(:,:), allocatable :: rb + !! Barycentric position + real(DP), dimension(:,:), allocatable :: vb + !! Barycentric velocity + real(DP), dimension(:,:), allocatable :: ah + !! Total heliocentric acceleration + real(DP), dimension(:,:), allocatable :: aobl + !! Barycentric accelerations of bodies due to central body oblatenes + real(DP), dimension(:,:), allocatable :: agr + !! Acceleration due to post-Newtonian correction + real(DP), dimension(:,:), allocatable :: atide + !! Tanngential component of acceleration of bodies due to tides + real(DP), dimension(:), allocatable :: ir3h + !! Inverse heliocentric radius term (1/rh**3) + integer(I4B), dimension(:), allocatable :: isperi + !! perihelion passage flag + real(DP), dimension(:), allocatable :: peri + !! perihelion distance + real(DP), dimension(:), allocatable :: atp + !! semimajor axis following perihelion passage + real(DP), dimension(:), allocatable :: a + !! Semimajor axis (pericentric distance for a parabolic orbit) + real(DP), dimension(:), allocatable :: e + !! Eccentricity + real(DP), dimension(:), allocatable :: inc + !! Inclination + real(DP), dimension(:), allocatable :: capom + !! Longitude of ascending node + real(DP), dimension(:), allocatable :: omega + !! Argument of pericenter + real(DP), dimension(:), allocatable :: capm + !! Mean anomaly + ! Note to developers: If you add components to this class, be sure to update methods and subroutines that traverse the + ! component list, such as setup_body and util_spill contains procedure(abstract_discard_body), deferred :: discard procedure(abstract_kick_body), deferred :: kick @@ -178,226 +223,397 @@ module swiftest procedure(abstract_accel), deferred :: accel ! These are concrete because the implementation is the same for all types of particles - procedure :: drift => swiftest_drift_body !! Loop through bodies and call Danby drift routine on heliocentric variables - procedure :: v2pv => swiftest_gr_vh2pv_body !! Converts from velocity to psudeovelocity for GR calculations using symplectic integrators - procedure :: pv2v => swiftest_gr_pv2vh_body !! Converts from psudeovelocity to velocity for GR calculations using symplectic integrators - procedure :: read_frame_bin => swiftest_io_read_frame_body !! I/O routine for writing out a single frame of time-series data for the central body - procedure :: read_in => swiftest_io_read_in_body !! Read in body initial conditions from an ascii file - procedure :: write_frame => swiftest_io_netcdf_write_frame_body !! I/O routine for writing out a single frame of time-series data for all bodies in the nbody_system in NetCDF format - procedure :: write_info => swiftest_io_netcdf_write_info_body !! Dump contents of particle information metadata to file - procedure :: el2xv => swiftest_orbel_el2xv_vec !! Convert orbital elements to position and velocity vectors - procedure :: xv2el => swiftest_orbel_xv2el_vec !! Convert position and velocity vectors to orbital elements - procedure :: setup => swiftest_util_setup_body !! A constructor that sets the number of bodies and allocates all allocatable arrays - procedure :: accel_user => swiftest_user_kick_getacch_body !! Add user-supplied heliocentric accelerations to planets - procedure :: append => swiftest_util_append_body !! Appends elements from one structure to another - procedure :: dealloc => swiftest_util_dealloc_body !! Deallocates all allocatable arrays - procedure :: fill => swiftest_util_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) - procedure :: get_peri => swiftest_util_peri_body !! Determine nbody_system pericenter passages for test particles - procedure :: resize => swiftest_util_resize_body !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. - procedure :: set_ir3 => swiftest_util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) - procedure :: sort => swiftest_util_sort_body !! Sorts body arrays by a sortable componen - procedure :: rearrange => swiftest_util_sort_rearrange_body !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => swiftest_util_spill_body !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) - generic :: read_frame => read_frame_bin !! Add the generic read frame for Fortran binary files + procedure :: drift => swiftest_drift_body + !! Loop through bodies and call Danby drift routine on heliocentric variables + procedure :: v2pv => swiftest_gr_vh2pv_body + !! Converts from velocity to psudeovelocity for GR calculations using symplectic integrators + procedure :: pv2v => swiftest_gr_pv2vh_body + !! Converts from psudeovelocity to velocity for GR calculations using symplectic integrators + procedure :: read_frame_bin => swiftest_io_read_frame_body + !! I/O routine for writing out a single frame of time-series data for the central body + procedure :: read_in => swiftest_io_read_in_body + !! Read in body initial conditions from an ascii file + procedure :: write_frame => swiftest_io_netcdf_write_frame_body + !! I/O routine for writing out a single frame of time-series data for all bodies in the nbody_system in NetCDF format + procedure :: write_info => swiftest_io_netcdf_write_info_body + !! Dump contents of particle information metadata to file + procedure :: el2xv => swiftest_orbel_el2xv_vec + !! Convert orbital elements to position and velocity vectors + procedure :: xv2el => swiftest_orbel_xv2el_vec + !! Convert position and velocity vectors to orbital elements + procedure :: setup => swiftest_util_setup_body + !! A constructor that sets the number of bodies and allocates all allocatable arrays + procedure :: accel_user => swiftest_user_kick_getacch_body + !! Add user-supplied heliocentric accelerations to planets + procedure :: append => swiftest_util_append_body + !! Appends elements from one structure to another + procedure :: dealloc => swiftest_util_dealloc_body + !! Deallocates all allocatable arrays + procedure :: fill => swiftest_util_fill_body + !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: get_peri => swiftest_util_peri_body + !! Determine nbody_system pericenter passages for test particles + procedure :: resize => swiftest_util_resize_body + !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + procedure :: set_ir3 => swiftest_util_set_ir3h + !! Sets the inverse heliocentric radius term (1/rh**3) + procedure :: sort => swiftest_util_sort_body + !! Sorts body arrays by a sortable componen + procedure :: rearrange => swiftest_util_sort_rearrange_body + !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure :: spill => swiftest_util_spill_body + !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + generic :: read_frame => read_frame_bin + !! Add the generic read frame for Fortran binary files #ifdef COARRAY - procedure :: coclone => swiftest_coarray_coclone_body !! Clones the image 1 body object to all other images in the coarray structure. - procedure :: cocollect => swiftest_coarray_cocollect_body !! Collects all body object array components from all images and combines them into the image 1 body object + procedure :: coclone => swiftest_coarray_coclone_body + !! Clones the image 1 body object to all other images in the coarray structure. + procedure :: cocollect => swiftest_coarray_cocollect_body + !! Collects all body object array components from all images and combines them into the image 1 body object #endif end type swiftest_body type, abstract, extends(base_object) :: swiftest_cb !> An abstract class for a generic central body in a Swiftest simulation - class(swiftest_particle_info), allocatable :: info !! Particle metadata information - integer(I4B) :: id = 0 !! External identifier (unique) - real(DP) :: mass = 0.0_DP !! Central body mass (units MU) - real(DP) :: Gmass = 0.0_DP !! Central mass gravitational term G * mass (units GU * MU) - real(DP) :: radius = 0.0_DP !! Central body radius (units DU) - real(DP) :: density = 1.0_DP !! Central body mass density - calculated internally (units MU / DU**3) - real(DP) :: j2rp2 = 0.0_DP !! J2*R^2 term for central body - real(DP) :: j4rp4 = 0.0_DP !! J4*R^4 term for central body - real(DP), dimension(:,:,:), allocatable :: c_lm !! Spherical Harmonics coefficients for the central body - real(DP), dimension(NDIM) :: aobl = 0.0_DP !! Barycentric acceleration due to central body oblatenes - real(DP), dimension(NDIM) :: atide = 0.0_DP !! Barycentric acceleration due to central body oblatenes - real(DP), dimension(NDIM) :: aoblbeg = 0.0_DP !! Barycentric acceleration due to central body oblatenes at beginning of step - real(DP), dimension(NDIM) :: aoblend = 0.0_DP !! Barycentric acceleration due to central body oblatenes at end of step - real(DP), dimension(NDIM) :: atidebeg = 0.0_DP !! Barycentric acceleration due to central body oblatenes at beginning of step - real(DP), dimension(NDIM) :: atideend = 0.0_DP !! Barycentric acceleration due to central body oblatenes at end of step - real(DP), dimension(NDIM) :: rb = 0.0_DP !! Barycentric position (units DU) - real(DP), dimension(NDIM) :: vb = 0.0_DP !! Barycentric velocity (units DU / TU) - real(DP), dimension(NDIM) :: agr = 0.0_DP !! Acceleration due to post-Newtonian correction - real(DP), dimension(NDIM) :: Ip = 0.0_DP !! Unitless principal moments of inertia (I1, I2, I3) / (MR**2). Principal axis rotation assumed. - real(DP), dimension(NDIM) :: rot = 0.0_DP !! Body rotation vector in inertial coordinate frame (units rad / TU) - real(DP) :: rotphase = 0.0_DP !! Body rotation phase about the rotation pole (0 to 1) - real(DP) :: k2 = 0.0_DP !! Tidal Love number - real(DP) :: Q = 0.0_DP !! Tidal quality factor - real(DP) :: tlag = 0.0_DP !! Tidal phase lag angle - real(DP), dimension(NDIM) :: L0 = 0.0_DP !! Initial angular momentum of the central body - real(DP), dimension(NDIM) :: dL = 0.0_DP !! Change in angular momentum of the central body - real(DP) :: GM0 = 0.0_DP !! Initial G*mass of the central body - real(DP) :: dGM = 0.0_DP !! Change in G*mass of the central body - real(DP) :: R0 = 0.0_DP !! Initial radius of the central body - real(DP) :: dR = 0.0_DP !! Change in the radius of the central body + class(swiftest_particle_info), allocatable :: info + !! Particle metadata information + integer(I4B) :: id = 0 + !! External identifier (unique) + real(DP) :: mass = 0.0_DP + !! Central body mass (units MU) + real(DP) :: Gmass = 0.0_DP + !! Central mass gravitational term G * mass (units GU * MU) + real(DP) :: radius = 0.0_DP + !! Central body radius (units DU) + real(DP) :: density = 1.0_DP + !! Central body mass density - calculated internally (units MU / DU**3) + real(DP) :: j2rp2 = 0.0_DP + !! J2*R^2 term for central body + real(DP) :: j4rp4 = 0.0_DP + !! J4*R^4 term for central body + real(DP), dimension(:,:,:), allocatable :: c_lm + !! Spherical Harmonics coefficients for the central body + real(DP), dimension(NDIM) :: aobl = 0.0_DP + !! Barycentric acceleration due to central body oblatenes + real(DP), dimension(NDIM) :: atide = 0.0_DP + !! Barycentric acceleration due to central body oblatenes + real(DP), dimension(NDIM) :: aoblbeg = 0.0_DP + !! Barycentric acceleration due to central body oblatenes at beginning of step + real(DP), dimension(NDIM) :: aoblend = 0.0_DP + !! Barycentric acceleration due to central body oblatenes at end of step + real(DP), dimension(NDIM) :: atidebeg = 0.0_DP + !! Barycentric acceleration due to central body oblatenes at beginning of step + real(DP), dimension(NDIM) :: atideend = 0.0_DP + !! Barycentric acceleration due to central body oblatenes at end of step + real(DP), dimension(NDIM) :: rb = 0.0_DP + !! Barycentric position (units DU) + real(DP), dimension(NDIM) :: vb = 0.0_DP + !! Barycentric velocity (units DU / TU) + real(DP), dimension(NDIM) :: agr = 0.0_DP + !! Acceleration due to post-Newtonian correction + real(DP), dimension(NDIM) :: Ip = 0.0_DP + !! Unitless principal moments of inertia (I1, I2, I3) / (MR**2). Principal axis rotation assumed. + real(DP), dimension(NDIM) :: rot = 0.0_DP + !! Body rotation vector in inertial coordinate frame (units rad / TU) + real(DP) :: rotphase = 0.0_DP + !! Body rotation phase about the rotation pole (0 to 1) + real(DP) :: k2 = 0.0_DP + !! Tidal Love number + real(DP) :: Q = 0.0_DP + !! Tidal quality factor + real(DP) :: tlag = 0.0_DP + !! Tidal phase lag angle + real(DP), dimension(NDIM) :: L0 = 0.0_DP + !! Initial angular momentum of the central body + real(DP), dimension(NDIM) :: dL = 0.0_DP + !! Change in angular momentum of the central body + real(DP) :: GM0 = 0.0_DP + !! Initial G*mass of the central body + real(DP) :: dGM = 0.0_DP + !! Change in G*mass of the central body + real(DP) :: R0 = 0.0_DP + !! Initial radius of the central body + real(DP) :: dR = 0.0_DP + !! Change in the radius of the central body contains - procedure :: rotphase_update => swiftest_drift_cb_rotphase_update !! updates the central body rotation phase - procedure :: dealloc => swiftest_util_dealloc_cb !! Deallocates all allocatables and resets all values to defaults - procedure :: read_in => swiftest_io_read_in_cb !! Read in central body initial conditions from an ASCII file - procedure :: write_frame => swiftest_io_netcdf_write_frame_cb !! I/O routine for writing out a single frame of time-series data for all bodies in the system in NetCDF format - procedure :: write_info => swiftest_io_netcdf_write_info_cb !! Dump contents of particle information metadata to file + procedure :: rotphase_update => swiftest_drift_cb_rotphase_update + !! updates the central body rotation phase + procedure :: dealloc => swiftest_util_dealloc_cb + !! Deallocates all allocatables and resets all values to defaults + procedure :: read_in => swiftest_io_read_in_cb + !! Read in central body initial conditions from an ASCII file + procedure :: write_frame => swiftest_io_netcdf_write_frame_cb + !! I/O routine for writing out a single frame of time-series data for all bodies in the system in NetCDF format + procedure :: write_info => swiftest_io_netcdf_write_info_cb + !! Dump contents of particle information metadata to file #ifdef COARRAY - procedure :: coclone => swiftest_coarray_coclone_cb !! Clones the image 1 body object to all other images in the coarray structure. + procedure :: coclone => swiftest_coarray_coclone_cb + !! Clones the image 1 body object to all other images in the coarray structure. #endif end type swiftest_cb type, abstract, extends(swiftest_body) :: swiftest_pl - !! Superclass that defines the generic elements of a Swiftest particle - real(DP), dimension(:), allocatable :: mass !! Body mass (units MU) - real(DP), dimension(:), allocatable :: Gmass !! Mass gravitational term G * mass (units GU * MU) - real(DP), dimension(:), allocatable :: rhill !! Body mass (units MU) - real(DP), dimension(:), allocatable :: renc !! Critical radius for close encounters - real(DP), dimension(:), allocatable :: radius !! Body radius (units DU) - real(DP), dimension(:), allocatable :: density !! Body mass density - calculated internally (units MU / DU**3) - real(DP), dimension(:,:), allocatable :: rbeg !! Position at beginning of step - real(DP), dimension(:,:), allocatable :: rend !! Position at end of step - real(DP), dimension(:,:), allocatable :: vbeg !! Velocity at beginning of step - real(DP), dimension(:,:), allocatable :: Ip !! Unitless principal moments of inertia (I1, I2, I3) / (MR**2). Principal axis rotation assumed. - real(DP), dimension(:,:), allocatable :: rot !! Body rotation vector in inertial coordinate frame (units rad / TU) - real(DP), dimension(:), allocatable :: k2 !! Tidal Love number - real(DP), dimension(:), allocatable :: Q !! Tidal quality factor - real(DP), dimension(:), allocatable :: tlag !! Tidal phase lag - integer(I4B), dimension(:,:), allocatable :: k_plpl !! Index array used to convert flattened the body-body comparison upper triangular matrix - integer(I8B) :: nplpl !! Number of body-body comparisons in the flattened upper triangular matrix - type(swiftest_kinship), dimension(:), allocatable :: kin !! Array of merger relationship structures that can account for multiple pairwise mergers in a single step - logical, dimension(:), allocatable :: lmtiny !! flag indicating whether this body is below the GMTINY cutoff value - integer(I4B) :: nplm = 0 !! number of bodies above the GMTINY limit - integer(I8B) :: nplplm !! Number of body (all massive)-body (only those above GMTINY) comparisons in the flattened upper triangular matrix - integer(I4B), dimension(:), allocatable :: nplenc !! number of encounters with other planets this time step - integer(I4B), dimension(:), allocatable :: ntpenc !! number of encounters with test particles this time step - !! Note to developers: If you add components to this class, be sure to update methods and subroutines that traverse the - !! component list, such as setup_pl and util_spill_pl + !! Superclass that defines the generic elements of a Swiftest particle + real(DP), dimension(:), allocatable :: mass + !! Body mass (units MU) + real(DP), dimension(:), allocatable :: Gmass + !! Mass gravitational term G * mass (units GU * MU) + real(DP), dimension(:), allocatable :: rhill + !! Body mass (units MU) + real(DP), dimension(:), allocatable :: renc + !! Critical radius for close encounters + real(DP), dimension(:), allocatable :: radius + !! Body radius (units DU) + real(DP), dimension(:), allocatable :: density + !! Body mass density - calculated internally (units MU / DU**3) + real(DP), dimension(:,:), allocatable :: rbeg + !! Position at beginning of step + real(DP), dimension(:,:), allocatable :: rend + !! Position at end of step + real(DP), dimension(:,:), allocatable :: vbeg + !! Velocity at beginning of step + real(DP), dimension(:,:), allocatable :: Ip + !! Unitless principal moments of inertia (I1, I2, I3) / (MR**2). Principal axis rotation assumed. + real(DP), dimension(:,:), allocatable :: rot + !! Body rotation vector in inertial coordinate frame (units rad / TU) + real(DP), dimension(:), allocatable :: k2 + !! Tidal Love number + real(DP), dimension(:), allocatable :: Q + !! Tidal quality factor + real(DP), dimension(:), allocatable :: tlag + !! Tidal phase lag + integer(I4B), dimension(:,:), allocatable :: k_plpl + !! Index array used to convert flattened the body-body comparison upper triangular matrix + integer(I8B) :: nplpl + !! Number of body-body comparisons in the flattened upper triangular matrix + type(swiftest_kinship), dimension(:), allocatable :: kin + !! Array of merger relationship structures that can account for multiple pairwise mergers in a single step + logical, dimension(:), allocatable :: lmtiny + !! flag indicating whether this body is below the GMTINY cutoff value + integer(I4B) :: nplm = 0 + !! number of bodies above the GMTINY limit + integer(I8B) :: nplplm + !! Number of body (all massive)-body (only those above GMTINY) comparisons in the flattened upper triangular matrix + integer(I4B), dimension(:), allocatable :: nplenc + !! number of encounters with other planets this time step + integer(I4B), dimension(:), allocatable :: ntpenc + !! number of encounters with test particles this time step + + ! Note to developers: If you add components to this class, be sure to update methods and subroutines that traverse the + ! component list, such as setup_pl and util_spill_pl contains ! Massive body-specific concrete methods ! These are concrete because they are the same implemenation for all integrators - procedure :: make_impactors => swiftest_util_make_impactors_pl !! Make impactors out of the current kinship relationships - procedure :: discard => swiftest_discard_pl !! Placeholder method for discarding massive bodies - procedure :: accel_int => swiftest_kick_getacch_int_pl !! Compute direct cross (third) term heliocentric accelerations of massive bodies - procedure :: accel_obl => swiftest_obl_acc_pl !! Compute the barycentric accelerations of bodies due to the oblateness of the central body - procedure :: setup => swiftest_util_setup_pl !! A base constructor that sets the number of bodies and allocates and initializes all arrays - procedure :: accel_sph => swiftest_sph_g_acc_pl_all !! Acceleration due ot spherical harmonics terms - ! procedure :: accel_tides => tides_kick_getacch_pl !! Compute the accelerations of bodies due to tidal interactions with the central body - procedure :: append => swiftest_util_append_pl !! Appends elements from one structure to another - procedure :: h2b => swiftest_util_coord_h2b_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) - procedure :: b2h => swiftest_util_coord_b2h_pl !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) - procedure :: vh2vb => swiftest_util_coord_vh2vb_pl !! Convert massive bodies from heliocentric to barycentric coordinates (velocity only) - procedure :: vb2vh => swiftest_util_coord_vb2vh_pl !! Convert massive bodies from barycentric to heliocentric coordinates (velocity only) - procedure :: rh2rb => swiftest_util_coord_rh2rb_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position only) - procedure :: dealloc => swiftest_util_dealloc_pl !! Deallocates all allocatable arrays - procedure :: fill => swiftest_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) - procedure :: flatten => swiftest_util_flatten_eucl_plpl !! Sets up the (i, j) -> k indexing used for the single-loop blocking Euclidean distance matrix - procedure :: rearray => swiftest_util_rearray_pl !! Clean up the massive body structures to remove discarded bodies and add new bodies - procedure :: resize => swiftest_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. - procedure :: reset_kinship => swiftest_util_reset_kinship_pl !! Resets the kinship status of bodies - procedure :: set_beg_end => swiftest_util_set_beg_end_pl !! Sets the beginning and ending positions and velocities of planets. - procedure :: set_mu => swiftest_util_set_mu_pl !! Method used to construct the vectorized form of the central body mass - procedure :: set_rhill => swiftest_util_set_rhill !! Calculates the Hill's radii for each body - procedure :: set_renc_I4B => swiftest_util_set_renc_I4B !! Sets the critical radius for encounter given an inpput integer scale factor - procedure :: set_renc_DP => swiftest_util_set_renc_DP !! Sets the critical radius for encounter given an input real scale factor - procedure :: sort => swiftest_util_sort_pl !! Sorts body arrays by a sortable component - procedure :: rearrange => swiftest_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => swiftest_util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: make_impactors => swiftest_util_make_impactors_pl + !! Make impactors out of the current kinship relationships + procedure :: discard => swiftest_discard_pl + !! Placeholder method for discarding massive bodies + procedure :: accel_int => swiftest_kick_getacch_int_pl + !! Compute direct cross (third) term heliocentric accelerations of massive bodies + procedure :: accel_non_spherical_cb => swiftest_non_spherical_cb_acc_pl + !! Compute the barycentric accelerations of bodies due to the oblateness of the central body + procedure :: setup => swiftest_util_setup_pl + !! A base constructor that sets the number of bodies and allocates and initializes all arrays + ! procedure :: accel_tides => tides_kick_getacch_pl + !! Compute the accelerations of bodies due to tidal interactions with the central body + procedure :: append => swiftest_util_append_pl + !! Appends elements from one structure to another + procedure :: h2b => swiftest_util_coord_h2b_pl + !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) + procedure :: b2h => swiftest_util_coord_b2h_pl + !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) + procedure :: vh2vb => swiftest_util_coord_vh2vb_pl + !! Convert massive bodies from heliocentric to barycentric coordinates (velocity only) + procedure :: vb2vh => swiftest_util_coord_vb2vh_pl + !! Convert massive bodies from barycentric to heliocentric coordinates (velocity only) + procedure :: rh2rb => swiftest_util_coord_rh2rb_pl + !! Convert massive bodies from heliocentric to barycentric coordinates (position only) + procedure :: dealloc => swiftest_util_dealloc_pl + !! Deallocates all allocatable arrays + procedure :: fill => swiftest_util_fill_pl + !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: flatten => swiftest_util_flatten_eucl_plpl + !! Sets up the (i, j) -> k indexing used for the single-loop blocking Euclidean distance matrix + procedure :: rearray => swiftest_util_rearray_pl + !! Clean up the massive body structures to remove discarded bodies and add new bodies + procedure :: resize => swiftest_util_resize_pl + !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + procedure :: reset_kinship => swiftest_util_reset_kinship_pl + !! Resets the kinship status of bodies + procedure :: set_beg_end => swiftest_util_set_beg_end_pl + !! Sets the beginning and ending positions and velocities of planets. + procedure :: set_mu => swiftest_util_set_mu_pl + !! Method used to construct the vectorized form of the central body mass + procedure :: set_rhill => swiftest_util_set_rhill + !! Calculates the Hill's radii for each body + procedure :: set_renc_I4B => swiftest_util_set_renc_I4B + !! Sets the critical radius for encounter given an inpput integer scale factor + procedure :: set_renc_DP => swiftest_util_set_renc_DP + !! Sets the critical radius for encounter given an input real scale factor + procedure :: sort => swiftest_util_sort_pl + !! Sorts body arrays by a sortable component + procedure :: rearrange => swiftest_util_sort_rearrange_pl + !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure :: spill => swiftest_util_spill_pl + !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) generic :: set_renc => set_renc_I4B, set_renc_DP #ifdef COARRAY - procedure :: coclone => swiftest_coarray_coclone_pl !! Clones the image 1 body object to all other images in the coarray structure. + procedure :: coclone => swiftest_coarray_coclone_pl + !! Clones the image 1 body object to all other images in the coarray structure. #endif end type swiftest_pl type, abstract, extends(swiftest_body) :: swiftest_tp - !! Superclass that defines the generic elements of a Swiftest test particle - integer(I4B), dimension(:,:), allocatable :: k_pltp !! Index array used to convert flattened the body-body comparison upper triangular matrix - integer(I8B) :: npltp !! Number of pl-tp comparisons in the flattened upper triangular matrix - integer(I4B), dimension(:), allocatable :: nplenc !! number of encounters with planets this time step - !! Note to developers: If you add components to this class, be sure to update methods and subroutines that traverse the - !! component list, such as swiftest_util_setup_tp and util_spill_tp + + !! Superclass that defines the generic elements of a Swiftest test particle + integer(I4B), dimension(:,:), allocatable :: k_pltp + !! Index array used to convert flattened the body-body comparison upper triangular matrix + integer(I8B) :: npltp + !! Number of pl-tp comparisons in the flattened upper triangular matrix + integer(I4B), dimension(:), allocatable :: nplenc + !! number of encounters with planets this time step + + ! Note to developers: If you add components to this class, be sure to update methods and subroutines that traverse the + ! component list, such as swiftest_util_setup_tp and util_spill_tp contains ! Test particle-specific concrete methods ! These are concrete because they are the same implemenation for all integrators - procedure :: discard => swiftest_discard_tp !! Check to see if test particles should be discarded based on their positions relative to the massive bodies - procedure :: accel_int => swiftest_kick_getacch_int_tp !! Compute direct cross (third) term heliocentric accelerations of test particles by massive bodies - procedure :: accel_obl => swiftest_obl_acc_tp !! Compute the barycentric accelerations of bodies due to the oblateness of the central body - procedure :: accel_sph => swiftest_sph_g_acc_tp_all !! acceleration due to spherical harmonics - procedure :: setup => swiftest_util_setup_tp !! A base constructor that sets the number of bodies and - procedure :: append => swiftest_util_append_tp !! Appends elements from one structure to another - procedure :: h2b => swiftest_util_coord_h2b_tp !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) - procedure :: b2h => swiftest_util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) - procedure :: vb2vh => swiftest_util_coord_vb2vh_tp !! Convert test particles from barycentric to heliocentric coordinates (velocity only) - procedure :: vh2vb => swiftest_util_coord_vh2vb_tp !! Convert test particles from heliocentric to barycentric coordinates (velocity only) - procedure :: rh2rb => swiftest_util_coord_rh2rb_tp !! Convert test particles from heliocentric to barycentric coordinates (position only) - procedure :: dealloc => swiftest_util_dealloc_tp !! Deallocates all allocatable arrays - procedure :: fill => swiftest_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) - procedure :: rearray => swiftest_util_rearray_tp !! Clean up the test particle structures to remove discarded bodies - procedure :: resize => swiftest_util_resize_tp !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. - procedure :: set_mu => swiftest_util_set_mu_tp !! Method used to construct the vectorized form of the central body mass - procedure :: sort => swiftest_util_sort_tp !! Sorts body arrays by a sortable component - procedure :: rearrange => swiftest_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => swiftest_util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: discard => swiftest_discard_tp + !! Check to see if test particles should be discarded based on their positions relative to the massive bodies + procedure :: accel_int => swiftest_kick_getacch_int_tp + !! Compute direct cross (third) term heliocentric accelerations of test particles by massive bodies + procedure :: accel_non_spherical_cb => swiftest_non_spherical_cb_acc_tp + !! Compute the barycentric accelerations of bodies due to the oblateness of the central body + procedure :: setup => swiftest_util_setup_tp + !! A base constructor that sets the number of bodies and + procedure :: append => swiftest_util_append_tp + !! Appends elements from one structure to another + procedure :: h2b => swiftest_util_coord_h2b_tp + !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) + procedure :: b2h => swiftest_util_coord_b2h_tp + !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) + procedure :: vb2vh => swiftest_util_coord_vb2vh_tp + !! Convert test particles from barycentric to heliocentric coordinates (velocity only) + procedure :: vh2vb => swiftest_util_coord_vh2vb_tp + !! Convert test particles from heliocentric to barycentric coordinates (velocity only) + procedure :: rh2rb => swiftest_util_coord_rh2rb_tp + !! Convert test particles from heliocentric to barycentric coordinates (position only) + procedure :: dealloc => swiftest_util_dealloc_tp + !! Deallocates all allocatable arrays + procedure :: fill => swiftest_util_fill_tp + !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: rearray => swiftest_util_rearray_tp + !! Clean up the test particle structures to remove discarded bodies + procedure :: resize => swiftest_util_resize_tp + !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + procedure :: set_mu => swiftest_util_set_mu_tp + !! Method used to construct the vectorized form of the central body mass + procedure :: sort => swiftest_util_sort_tp + !! Sorts body arrays by a sortable component + procedure :: rearrange => swiftest_util_sort_rearrange_tp + !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure :: spill => swiftest_util_spill_tp + !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) #ifdef COARRAY - procedure :: coclone => swiftest_coarray_coclone_tp !! Clones the image 1 object to all other images in the coarray structure. - procedure :: cocollect => swiftest_coarray_cocollect_tp !! Collects all object array components from all images and combines them into the image 1 object + procedure :: coclone => swiftest_coarray_coclone_tp + !! Clones the image 1 object to all other images in the coarray structure. + procedure :: cocollect => swiftest_coarray_cocollect_tp + !! Collects all object array components from all images and combines them into the image 1 object #endif end type swiftest_tp !> An abstract class for a basic Swiftest nbody system type, abstract, extends(base_nbody_system) :: swiftest_nbody_system - !! This superclass contains a minimial nbody_system of a set of test particles (tp), massive bodies (pl), and a central body (cb) - !! The full swiftest_nbody_system type that is used as the parent class of all integrators is defined in collision - - class(swiftest_cb), allocatable :: cb !! Central body data structure - class(swiftest_pl), allocatable :: pl !! Massive body data structure - class(swiftest_tp), allocatable :: tp !! Test particle data structure - - class(swiftest_tp), allocatable :: tp_discards !! Discarded test particle data structure - class(swiftest_pl), allocatable :: pl_discards !! Discarded massive body particle data structure - class(swiftest_pl), allocatable :: pl_adds !! List of added bodies in mergers or collisions - class(swiftest_tp), allocatable :: tp_adds !! List of added bodies in mergers or collisions - class(encounter_list), allocatable :: pltp_encounter !! List of massive body-test particle encounters in a single step - class(encounter_list), allocatable :: plpl_encounter !! List of massive body-massive body encounters in a single step - class(collision_list_plpl), allocatable :: plpl_collision !! List of massive body-massive body collisions in a single step - class(collision_list_pltp), allocatable :: pltp_collision !! List of massive body-test particle collisions in a single step - class(collision_basic), allocatable :: collider !! Collision system object - class(encounter_storage), allocatable :: encounter_history !! Stores encounter history for later retrieval and saving to file - class(collision_storage), allocatable :: collision_history !! Stores encounter history for later retrieval and saving to file - - integer(I4B) :: maxid = -1 !! The current maximum particle id number - real(DP) :: t = -1.0_DP !! Integration current time - real(DP) :: GMtot = 0.0_DP !! Total nbody_system mass - used for barycentric coordinate conversion - real(DP) :: ke_orbit = 0.0_DP !! nbody_system orbital kinetic energy - real(DP) :: ke_spin = 0.0_DP !! nbody_system spin kinetic energy - real(DP) :: pe = 0.0_DP !! nbody_system potential energy - real(DP) :: be = 0.0_DP !! nbody_system binding energy of all bodies - real(DP) :: te = 0.0_DP !! nbody_system total energy - real(DP) :: oblpot = 0.0_DP !! nbody_system potential energy due to oblateness of the central body - real(DP), dimension(NDIM) :: L_orbit = 0.0_DP !! nbody_system orbital angular momentum vector - real(DP), dimension(NDIM) :: L_spin = 0.0_DP !! nbody_system spin angular momentum vector - real(DP), dimension(NDIM) :: L_total = 0.0_DP !! nbody_system angular momentum vector - real(DP) :: ke_orbit_orig = 0.0_DP !! Initial orbital kinetic energy - real(DP) :: ke_spin_orig = 0.0_DP !! Initial spin kinetic energy - real(DP) :: pe_orig = 0.0_DP !! Initial potential energy - real(DP) :: be_orig = 0.0_DP !! Initial gravitational binding energy - real(DP) :: te_orig = 0.0_DP !! Initial total energy (sum of all sources of energy tracked) - real(DP) :: be_cb = 0.0_DP !! Binding energy of central body (usually orders of magnitude larger than the rest of the system, and therefore tracked seperately) - real(DP) :: E_orbit_orig = 0.0_DP !! Initial orbital energy - real(DP) :: GMtot_orig = 0.0_DP !! Initial nbody_system mass - real(DP), dimension(NDIM) :: L_total_orig = 0.0_DP !! Initial total angular momentum vector - real(DP), dimension(NDIM) :: L_orbit_orig = 0.0_DP !! Initial orbital angular momentum - real(DP), dimension(NDIM) :: L_spin_orig = 0.0_DP !! Initial spin angular momentum vector - real(DP), dimension(NDIM) :: L_escape = 0.0_DP !! Angular momentum of bodies that escaped the nbody_system (used for bookeeping) - real(DP) :: GMescape = 0.0_DP !! Mass of bodies that escaped the nbody_system (used for bookeeping) - real(DP) :: E_collisions = 0.0_DP !! Energy lost from nbody_system due to collisions - real(DP) :: E_untracked = 0.0_DP !! Energy gained from nbody_system due to escaped bodies + !! This superclass contains a minimial nbody_system of a set of test particles (tp), massive bodies (pl), and a central + !! body (cb). + class(swiftest_cb), allocatable :: cb + !! Central body data structure + class(swiftest_pl), allocatable :: pl + !! Massive body data structure + class(swiftest_tp), allocatable :: tp + !! Test particle data structure + class(swiftest_tp), allocatable :: tp_discards + !! Discarded test particle data structure + class(swiftest_pl), allocatable :: pl_discards + !! Discarded massive body particle data structure + class(swiftest_pl), allocatable :: pl_adds + !! List of added bodies in mergers or collisions + class(swiftest_tp), allocatable :: tp_adds + !! List of added bodies in mergers or collisions + class(encounter_list), allocatable :: pltp_encounter + !! List of massive body-test particle encounters in a single step + class(encounter_list), allocatable :: plpl_encounter + !! List of massive body-massive body encounters in a single step + class(collision_list_plpl), allocatable :: plpl_collision + !! List of massive body-massive body collisions in a single step + class(collision_list_pltp), allocatable :: pltp_collision + !! List of massive body-test particle collisions in a single step + class(collision_basic), allocatable :: collider + !! Collision system object + class(encounter_storage), allocatable :: encounter_history + !! Stores encounter history for later retrieval and saving to file + class(collision_storage), allocatable :: collision_history + !! Stores encounter history for later retrieval and saving to file + integer(I4B) :: maxid = -1 + !! The current maximum particle id number + real(DP) :: t = -1.0_DP + !! Integration current time + real(DP) :: GMtot = 0.0_DP + !! Total nbody_system mass - used for barycentric coordinate conversion + real(DP) :: ke_orbit = 0.0_DP + !! nbody_system orbital kinetic energy + real(DP) :: ke_spin = 0.0_DP + !! nbody_system spin kinetic energy + real(DP) :: pe = 0.0_DP + !! nbody_system potential energy + real(DP) :: be = 0.0_DP + !! nbody_system binding energy of all bodies + real(DP) :: te = 0.0_DP + !! nbody_system total energy + real(DP) :: oblpot = 0.0_DP + !! nbody_system potential energy due to oblateness of the central body + real(DP), dimension(NDIM) :: L_orbit = 0.0_DP + !! nbody_system orbital angular momentum vector + real(DP), dimension(NDIM) :: L_spin = 0.0_DP + !! nbody_system spin angular momentum vector + real(DP), dimension(NDIM) :: L_total = 0.0_DP + !! nbody_system angular momentum vector + real(DP) :: ke_orbit_orig = 0.0_DP + !! Initial orbital kinetic energy + real(DP) :: ke_spin_orig = 0.0_DP + !! Initial spin kinetic energy + real(DP) :: pe_orig = 0.0_DP + !! Initial potential energy + real(DP) :: be_orig = 0.0_DP + !! Initial gravitational binding energy + real(DP) :: te_orig = 0.0_DP + !! Initial total energy (sum of all sources of energy tracked) + real(DP) :: be_cb = 0.0_DP + !! Binding energy of central body (usually orders of magnitude larger than the rest of the system, and therefore tracked + !! seperately) + real(DP) :: E_orbit_orig = 0.0_DP + !! Initial orbital energy + real(DP) :: GMtot_orig = 0.0_DP + !! Initial nbody_system mass + real(DP), dimension(NDIM) :: L_total_orig = 0.0_DP + !! Initial total angular momentum vector + real(DP), dimension(NDIM) :: L_orbit_orig = 0.0_DP + !! Initial orbital angular momentum + real(DP), dimension(NDIM) :: L_spin_orig = 0.0_DP + !! Initial spin angular momentum vector + real(DP), dimension(NDIM) :: L_escape = 0.0_DP + !! Angular momentum of bodies that escaped the nbody_system (used for bookeeping) + real(DP) :: GMescape = 0.0_DP + !! Mass of bodies that escaped the nbody_system (used for bookeeping) + real(DP) :: E_collisions = 0.0_DP + !! Energy lost from nbody_system due to collisions + real(DP) :: E_untracked = 0.0_DP + !! Energy gained from nbody_system due to escaped bodies ! Energy, momentum, and mass errors (used in error reporting) real(DP) :: ke_orbit_error = 0.0_DP @@ -415,44 +631,73 @@ module swiftest real(DP) :: Mtot_error = 0.0_DP real(DP) :: Mescape_error = 0.0_DP - logical :: lbeg !! True if this is the beginning of a step. This is used so that test particle steps can be calculated - !! separately from massive bodies. Massive body variables are saved at half steps, and passed to - !! the test particles - logical :: lfirst_io = .true. !! Flag to indicate that this is the first time to write to a file - logical :: lfirst_peri = .true. !! Flag to indicate that this is the first pericenter passage + logical :: lbeg + !! True if this is the beginning of a step. This is used so that test particle steps can be calculated separately from + !! massive bodies. Massive body variables are saved at half steps, and passed to the test particles + logical :: lfirst_io = .true. + !! Flag to indicate that this is the first time to write to a file + logical :: lfirst_peri = .true. + !! Flag to indicate that this is the first pericenter passage contains !> Each integrator will have its own version of the step procedure(abstract_step_system), deferred :: step ! Concrete classes that are common to the basic integrator (only test particles considered for discard) - procedure :: discard => swiftest_discard_system !! Perform a discard step on the nbody_system - procedure :: compact_output => swiftest_io_compact_output !! Prints out out terminal output when display_style is set to COMPACT - procedure :: conservation_report => swiftest_io_conservation_report !! Compute energy and momentum and print out the change with time - procedure :: display_run_information => swiftest_io_display_run_information !! Displays helpful information about the run - procedure :: dump => swiftest_io_dump_system !! Dump the state of the nbody_system to a file - procedure :: get_t0_values => swiftest_io_netcdf_get_t0_values_system !! Validates the dump file to check whether the dump file initial conditions duplicate the last frame of the netcdf output. - procedure :: read_frame => swiftest_io_netcdf_read_frame_system !! Read in a frame of input data from file - procedure :: read_hdr => swiftest_io_netcdf_read_hdr_system !! Read a header for an output frame in NetCDF format - procedure :: write_hdr => swiftest_io_netcdf_write_hdr_system !! Write a header for an output frame in NetCDF format - procedure :: read_particle_info => swiftest_io_netcdf_read_particle_info_system !! Read in particle metadata from file - procedure :: read_in => swiftest_io_read_in_system !! Reads the initial conditions for an nbody system - procedure :: write_frame => swiftest_io_netcdf_write_frame_system !! Write a frame of input data from file - procedure :: obl_pot => swiftest_obl_pot_system !! Compute the contribution to the total gravitational potential due solely to the oblateness of the central body - procedure :: dealloc => swiftest_util_dealloc_system !! Deallocates all allocatables and resets all values to defaults. Acts as a base for a finalizer - procedure :: get_energy_and_momentum => swiftest_util_get_energy_and_momentum_system !! Calculates the total nbody_system energy and momentum - procedure :: get_idvals => swiftest_util_get_idvalues_system !! Returns an array of all id values in use in the nbody_system - procedure :: rescale => swiftest_util_rescale_system !! Rescales the nbody_system into a new set of units - procedure :: initialize_output_file => swiftest_io_initialize_output_file_system !! Write a frame of input data from file - procedure :: initialize => swiftest_util_setup_initialize_system !! Initialize the nbody_system from input files - procedure :: init_particle_info => swiftest_util_setup_initialize_particle_info_system !! Initialize the nbody_system from input files - ! procedure :: step_spin => tides_step_spin_system !! Steps the spins of the massive & central bodies due to tides. - procedure :: set_msys => swiftest_util_set_msys !! Sets the value of msys from the masses of nbody_system bodies. - procedure :: validate_ids => swiftest_util_valid_id_system !! Validate the numerical ids passed to the nbody_system and save the maximum value + procedure :: discard => swiftest_discard_system + !! Perform a discard step on the nbody_system + procedure :: compact_output => swiftest_io_compact_output + !! Prints out out terminal output when display_style is set to COMPACT + procedure :: conservation_report => swiftest_io_conservation_report + !! Compute energy and momentum and print out the change with time + procedure :: display_run_information => swiftest_io_display_run_information + !! Displays helpful information about the run + procedure :: dump => swiftest_io_dump_system + !! Dump the state of the nbody_system to a file + procedure :: get_t0_values => swiftest_io_netcdf_get_t0_values_system + !! Validates the dump file to check whether the dump file initial conditions duplicate the last frame of the netcdf output. + procedure :: read_frame => swiftest_io_netcdf_read_frame_system + !! Read in a frame of input data from file + procedure :: read_hdr => swiftest_io_netcdf_read_hdr_system + !! Read a header for an output frame in NetCDF format + procedure :: write_hdr => swiftest_io_netcdf_write_hdr_system + !! Write a header for an output frame in NetCDF format + procedure :: read_particle_info => swiftest_io_netcdf_read_particle_info_system + !! Read in particle metadata from file + procedure :: read_in => swiftest_io_read_in_system + !! Reads the initial conditions for an nbody system + procedure :: write_frame => swiftest_io_netcdf_write_frame_system + !! Write a frame of input data from file + procedure :: obl_pot => swiftest_obl_pot_system + !! Compute the contribution to the total gravitational potential due solely to the oblateness of the central body + procedure :: dealloc => swiftest_util_dealloc_system + !! Deallocates all allocatables and resets all values to defaults. Acts as a base for a finalizer + procedure :: get_energy_and_momentum => swiftest_util_get_energy_and_momentum_system + !! Calculates the total nbody_system energy and momentum + procedure :: get_idvals => swiftest_util_get_idvalues_system + !! Returns an array of all id values in use in the nbody_system + procedure :: rescale => swiftest_util_rescale_system + !! Rescales the nbody_system into a new set of units + procedure :: initialize_output_file => swiftest_io_initialize_output_file_system + !! Write a frame of input data from file + procedure :: initialize => swiftest_util_setup_initialize_system + !! Initialize the nbody_system from input files + procedure :: init_particle_info => swiftest_util_setup_initialize_particle_info_system + !! Initialize the nbody_system from input files + ! procedure :: step_spin => tides_step_spin_system + !! Steps the spins of the massive & central bodies due to tides. + procedure :: set_msys => swiftest_util_set_msys + !! Sets the value of msys from the masses of nbody_system bodies. + procedure :: validate_ids => swiftest_util_valid_id_system + !! Validate the numerical ids passed to the nbody_system and save the maximum value #ifdef COARRAY - procedure :: coclone => swiftest_coarray_coclone_system !! Clones the image 1 body object to all other images in the coarray structure. - procedure :: coarray_collect => swiftest_coarray_collect_system !! Collects all the test particles from other images into the image #1 test particle system - procedure :: coarray_distribute => swiftest_coarray_distribute_system !! Distributes test particles from image #1 out to all images. - procedure :: coarray_balance => swiftest_coarray_balance_system !! Checks whether or not the test particle coarrays need to be rebalanced. + procedure :: coclone => swiftest_coarray_coclone_system + !! Clones the image 1 body object to all other images in the coarray structure. + procedure :: coarray_collect => swiftest_coarray_collect_system + !! Collects all the test particles from other images into the image #1 test particle system + procedure :: coarray_distribute => swiftest_coarray_distribute_system + !! Distributes test particles from image #1 out to all images. + procedure :: coarray_balance => swiftest_coarray_balance_system + !! Checks whether or not the test particle coarrays need to be rebalanced. #endif end type swiftest_nbody_system @@ -461,436 +706,633 @@ module swiftest subroutine abstract_accel(self, nbody_system, param, t, lbeg) import swiftest_body, swiftest_nbody_system, swiftest_parameters, DP - class(swiftest_body), intent(inout) :: self !! Swiftest body data structure - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! Current simulation time - logical, intent(in) :: lbeg !! Optional argument that determines whether or not this is the beginning or end of the step + class(swiftest_body), intent(inout) :: self + !! Swiftest body data structure + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + real(DP), intent(in) :: t + !! Current simulation time + logical, intent(in) :: lbeg + !! Optional argument that determines whether or not this is the beginning or end of the step end subroutine abstract_accel subroutine abstract_discard_body(self, nbody_system, param) import swiftest_body, swiftest_nbody_system, swiftest_parameters - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine abstract_discard_body subroutine abstract_kick_body(self, nbody_system, param, t, dt, lbeg) import swiftest_body, swiftest_nbody_system, swiftest_parameters, DP implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest generic body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system objec - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! Current time - real(DP), intent(in) :: dt !! Stepsize - logical, intent(in) :: lbeg !! Logical flag indicating whether this is the beginning of the half step or not. + class(swiftest_body), intent(inout) :: self + !! Swiftest generic body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system objec + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + real(DP), intent(in) :: t + !! Current time + real(DP), intent(in) :: dt + !! Stepsize + logical, intent(in) :: lbeg + !! Logical flag indicating whether this is the beginning of the half step or not. end subroutine abstract_kick_body subroutine abstract_set_mu(self, cb) import swiftest_body, swiftest_cb - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine abstract_set_mu subroutine abstract_step_body(self, nbody_system, param, t, dt) import DP, swiftest_body, swiftest_nbody_system, swiftest_parameters implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody_system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! Simulation time - real(DP), intent(in) :: dt !! Current stepsize + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody_system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + real(DP), intent(in) :: t + !! Simulation time + real(DP), intent(in) :: dt + !! Current stepsize end subroutine abstract_step_body subroutine abstract_step_system(self, param, t, dt) import DP, swiftest_nbody_system, swiftest_parameters implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody_system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! Simulation time - real(DP), intent(in) :: dt !! Current stepsize + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody_system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + real(DP), intent(in) :: t + !! Simulation time + real(DP), intent(in) :: dt + !! Current stepsize end subroutine abstract_step_system end interface interface module subroutine swiftest_discard_pl(self, nbody_system, param) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameter + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameter end subroutine swiftest_discard_pl module subroutine swiftest_discard_system(self, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody_system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody_system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_discard_system module subroutine swiftest_discard_tp(self, nbody_system, param) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_discard_tp module subroutine swiftest_drift_all(mu, x, v, n, param, dt, lmask, iflag) implicit none - real(DP), dimension(:), intent(in) :: mu !! Vector of gravitational constants - real(DP), dimension(:,:), intent(inout) :: x, v !! Position and velocity vectors - integer(I4B), intent(in) :: n !! number of bodies - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: dt !! Stepsize - logical, dimension(:), intent(in) :: lmask !! Logical mask of size self%nbody that determines which bodies to drift. - integer(I4B), dimension(:), intent(out) :: iflag !! Vector of error flags. 0 means no problem + real(DP), dimension(:), intent(in) :: mu + !! Vector of gravitational constants + real(DP), dimension(:,:), intent(inout) :: x, v + !! Position and velocity vectors + integer(I4B), intent(in) :: n + !! number of bodies + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters + real(DP), intent(in) :: dt + !! Stepsize + logical, dimension(:), intent(in) :: lmask + !! Logical mask of size self%nbody that determines which bodies to drift. + integer(I4B), dimension(:), intent(out) :: iflag + !! Vector of error flags. 0 means no problem end subroutine swiftest_drift_all module subroutine swiftest_drift_body(self, nbody_system, param, dt) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest particle data structure - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: dt !! Stepsize + class(swiftest_body), intent(inout) :: self + !! Swiftest particle data structure + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters + real(DP), intent(in) :: dt + !! Stepsize end subroutine swiftest_drift_body pure elemental module subroutine swiftest_drift_one(mu, rx, ry, rz, vx, vy, vz, dt, iflag) !$omp declare simd(swiftest_drift_one) implicit none - real(DP), intent(in) :: mu !! G * (Mcb + m), G = gravitational constant, Mcb = mass of central body, m = mass of body to drift - real(DP), intent(inout) :: rx, ry, rz, vx, vy, vz !! Position and velocity of body to drift - real(DP), intent(in) :: dt !! Step size - integer(I4B), intent(out) :: iflag !! iflag : error status flag for Danby drift (0 = OK, nonzero = ERROR) + real(DP), intent(in) :: mu + !! G * (Mcb + m), G = gravitational constant, Mcb = mass of central body, m = mass of body to drift + real(DP), intent(inout) :: rx, ry, rz, vx, vy, vz + !! Position and velocity of body to drift + real(DP), intent(in) :: dt + !! Step size + integer(I4B), intent(out) :: iflag + !! iflag : error status flag for Danby drift (0 = OK, nonzero = ERROR) end subroutine swiftest_drift_one module subroutine swiftest_drift_cb_rotphase_update(self, param, dt) - !! Author : Kaustub Anand - !! subroutine to update the rotation phase of the central body - !! Units: radians - !! initial 0 is set at the x-axis + + !! Author : Kaustub Anand + + !! subroutine to update the rotation phase of the central body + + !! Units: radians + + !! initial 0 is set at the x-axis ! Arguments - class(swiftest_cb), intent(inout) :: self !! Swiftest central body data structure - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: dt !! Stepsize + class(swiftest_cb), intent(inout) :: self + !! Swiftest central body data structure + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters + real(DP), intent(in) :: dt + !! Stepsize end subroutine module subroutine swiftest_driver(integrator, param_file_name, display_style) implicit none - character(len=:), intent(in), allocatable :: integrator !! Symbolic code of the requested integrator - character(len=:), intent(in), allocatable :: param_file_name !! Name of the input parameters file - character(len=:), intent(in), allocatable :: display_style !! Style of the output display {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD" + character(len=:), intent(in), allocatable :: integrator + !! Symbolic code of the requested integrator + character(len=:), intent(in), allocatable :: param_file_name + !! Name of the input parameters file + character(len=:), intent(in), allocatable :: display_style + !! Style of the output display {"STANDARD", "COMPACT", "PROGRESS"}). Default is "STANDARD" end subroutine swiftest_driver pure module subroutine swiftest_gr_kick_getaccb_ns_body(self, nbody_system, param) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest generic body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self + !! Swiftest generic body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_gr_kick_getaccb_ns_body pure module subroutine swiftest_gr_kick_getacch(mu, x, lmask, n, inv_c2, agr) implicit none - real(DP), dimension(:), intent(in) :: mu !! Gravitational constant - real(DP), dimension(:,:), intent(in) :: x !! Position vectors - logical, dimension(:), intent(in) :: lmask !! Logical mask indicating which bodies to compute - integer(I4B), intent(in) :: n !! Total number of bodies - real(DP), intent(in) :: inv_c2 !! Inverse speed of light squared: 1 / c**2 - real(DP), dimension(:,:), intent(out) :: agr !! Accelerations + real(DP), dimension(:), intent(in) :: mu + !! Gravitational constant + real(DP), dimension(:,:), intent(in) :: x + !! Position vectors + logical, dimension(:), intent(in) :: lmask + !! Logical mask indicating which bodies to compute + integer(I4B), intent(in) :: n + !! Total number of bodies + real(DP), intent(in) :: inv_c2 + !! Inverse speed of light squared: 1 / c**2 + real(DP), dimension(:,:), intent(out) :: agr + !! Accelerations end subroutine swiftest_gr_kick_getacch pure elemental module subroutine swiftest_gr_p4_pos_kick(inv_c2, rx, ry, rz, vx, vy, vz, dt) implicit none - real(DP), intent(in) :: inv_c2 !! One over speed of light squared (1/c**2) - real(DP), intent(inout) :: rx, ry, rz !! Position vector - real(DP), intent(in) :: vx, vy, vz !! Velocity vector - real(DP), intent(in) :: dt !! Step size + real(DP), intent(in) :: inv_c2 + !! One over speed of light squared (1/c**2) + real(DP), intent(inout) :: rx, ry, rz + !! Position vector + real(DP), intent(in) :: vx, vy, vz + !! Velocity vector + real(DP), intent(in) :: dt + !! Step size end subroutine swiftest_gr_p4_pos_kick pure module subroutine swiftest_gr_pseudovel2vel(param, mu, rh, pv, vh) implicit none - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: mu !! G * (Mcb + m), G = gravitational constant, Mcb = mass of central body, m = mass of body - real(DP), dimension(:), intent(in) :: rh !! Swiftestcentric position vector - real(DP), dimension(:), intent(in) :: pv !! Pseudovelocity velocity vector - see Saha & Tremain (1994), eq. (32) - real(DP), dimension(:), intent(out) :: vh !! Swiftestcentric velocity vector + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters + real(DP), intent(in) :: mu + !! G * (Mcb + m), G = gravitational constant, Mcb = mass of central body, m = mass of body + real(DP), dimension(:), intent(in) :: rh + !! Swiftestcentric position vector + real(DP), dimension(:), intent(in) :: pv + !! Pseudovelocity velocity vector - see Saha & Tremain (1994), eq. (32) + real(DP), dimension(:), intent(out) :: vh + !! Swiftestcentric velocity vector end subroutine swiftest_gr_pseudovel2vel pure module subroutine swiftest_gr_pv2vh_body(self, param) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest particle object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self + !! Swiftest particle object + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_gr_pv2vh_body pure module subroutine swiftest_gr_vel2pseudovel(param, mu, rh, vh, pv) implicit none - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: mu !! G * (Mcb + m), G = gravitational constant, Mcb = mass of central body, m = mass of body - real(DP), dimension(:), intent(in) :: rh !! Swiftestcentric position vector - real(DP), dimension(:), intent(in) :: vh !! Swiftestcentric velocity vector - real(DP), dimension(:), intent(out) :: pv !! Pseudovelocity vector - see Saha & Tremain (1994), eq. (32) + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters + real(DP), intent(in) :: mu + !! G * (Mcb + m), G = gravitational constant, Mcb = mass of central body, m = mass of body + real(DP), dimension(:), intent(in) :: rh + !! Swiftestcentric position vector + real(DP), dimension(:), intent(in) :: vh + !! Swiftestcentric velocity vector + real(DP), dimension(:), intent(out) :: pv + !! Pseudovelocity vector - see Saha & Tremain (1994), eq. (32) end subroutine swiftest_gr_vel2pseudovel pure module subroutine swiftest_gr_vh2pv_body(self, param) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest particle object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self + !! Swiftest particle object + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_gr_vh2pv_body module subroutine swiftest_io_compact_output(self, param, timer) implicit none - 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 + 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 end subroutine swiftest_io_compact_output module subroutine swiftest_io_conservation_report(self, param, lterminal) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Input colleciton of user-defined parameters - logical, intent(in) :: lterminal !! Indicates whether to output information to the terminal screen + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Input colleciton of user-defined parameters + logical, intent(in) :: lterminal + !! Indicates whether to output information to the terminal screen end subroutine swiftest_io_conservation_report module subroutine swiftest_io_display_run_information(self, param, integration_timer, phase) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - type(walltimer), intent(inout) :: integration_timer !! Object used for computing elapsed wall time - character(len=*), optional, intent(in) :: phase !! One of "first" or "last" + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + type(walltimer), intent(inout) :: integration_timer + !! Object used for computing elapsed wall time + character(len=*), optional, intent(in) :: phase + !! One of "first" or "last" end subroutine swiftest_io_display_run_information module subroutine swiftest_io_dump_param(self, param_file_name) implicit none - class(swiftest_parameters),intent(in) :: self !! Output collection of parameters - character(len=*), intent(in) :: param_file_name !! Parameter input file name (i.e. param.in) + class(swiftest_parameters),intent(in) :: self + !! Output collection of parameters + character(len=*), intent(in) :: param_file_name + !! Parameter input file name (i.e. param.in) end subroutine swiftest_io_dump_param module subroutine swiftest_io_dump_system(self, param, system_history) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody_system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - class(swiftest_storage), intent(inout) :: system_history !! Stores the system history between output dumps + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody_system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + class(swiftest_storage), intent(inout) :: system_history + !! Stores the system history between output dumps end subroutine swiftest_io_dump_system module subroutine swiftest_io_dump_storage(self, param) implicit none - class(swiftest_storage), intent(inout) :: self !! Swiftest simulation history storage object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_storage), intent(inout) :: self + !! Swiftest simulation history storage object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_dump_storage module subroutine swiftest_io_get_args(integrator, param_file_name, display_style, from_cli) implicit none - 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" - logical, intent(in) :: from_cli !! If true, get command-line arguments. Otherwise, use the values of the input variables + 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" + logical, intent(in) :: from_cli + !! If true, get command-line arguments. Otherwise, use the values of the input variables end subroutine swiftest_io_get_args module function swiftest_io_get_token(buffer, ifirst, ilast, ierr) result(token) implicit none - character(len=*), intent(in) :: buffer !! Input string buffer - integer(I4B), intent(inout) :: ifirst !! Index of the buffer at which to start the search for a token - integer(I4B), intent(out) :: ilast !! Index of the buffer at the end of the returned token - integer(I4B), intent(out) :: ierr !! Error code - character(len=:), allocatable :: token !! Returned token string + character(len=*), intent(in) :: buffer + !! Input string buffer + integer(I4B), intent(inout) :: ifirst + !! Index of the buffer at which to start the search for a token + integer(I4B), intent(out) :: ilast + !! Index of the buffer at the end of the returned token + integer(I4B), intent(out) :: ierr + !! Error code + character(len=:), allocatable :: token + !! Returned token string end function swiftest_io_get_token module subroutine swiftest_io_log_one_message(file, message) implicit none - character(len=*), intent(in) :: file !! Name of file to log + character(len=*), intent(in) :: file + !! Name of file to log character(len=*), intent(in) :: message end subroutine swiftest_io_log_one_message module subroutine swiftest_io_log_start(param, file, header) implicit none - class(swiftest_parameters), intent(in) :: param !! Current Swiftest run configuration parameters - character(len=*), intent(in) :: file !! Name of file to log - character(len=*), intent(in) :: header !! Header to print at top of log file + class(swiftest_parameters), intent(in) :: param + !! Current Swiftest run configuration parameters + character(len=*), intent(in) :: file + !! Name of file to log + character(len=*), intent(in) :: header + !! Header to print at top of log file end subroutine swiftest_io_log_start module subroutine swiftest_io_netcdf_flush(self, param) implicit none - class(swiftest_netcdf_parameters), intent(inout) :: self !! Parameters used to identify a particular NetCDF dataset - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_netcdf_parameters), intent(inout) :: self + !! Parameters used to identify a particular NetCDF dataset + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_flush module subroutine swiftest_io_netcdf_get_t0_values_system(self, nc, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to identify a particular NetCDF dataset - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to identify a particular NetCDF dataset + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_get_t0_values_system module subroutine swiftest_io_netcdf_get_valid_masks(self, plmask, tpmask, plmmask, Gmtiny) implicit none - class(swiftest_netcdf_parameters), intent(inout) :: self !! Parameters used to identify a particular NetCDF dataset - logical, dimension(:), allocatable, intent(out) :: plmask !! Logical mask indicating which bodies are massive bodies - logical, dimension(:), allocatable, intent(out) :: tpmask !! Logical mask indicating which bodies are test particles - logical, dimension(:), allocatable, intent(out), optional :: plmmask !! Logical mask indicating which bodies are fully interacting massive bodies - real(DP), intent(in), optional :: Gmtiny !! The cutoff G*mass between semi-interacting and fully interacting massive bodies + class(swiftest_netcdf_parameters), intent(inout) :: self + !! Parameters used to identify a particular NetCDF dataset + logical, dimension(:), allocatable, intent(out) :: plmask + !! Logical mask indicating which bodies are massive bodies + logical, dimension(:), allocatable, intent(out) :: tpmask + !! Logical mask indicating which bodies are test particles + logical, dimension(:), allocatable, intent(out), optional :: plmmask + !! Logical mask indicating which bodies are fully interacting massive bodies + real(DP), intent(in), optional :: Gmtiny + !! The cutoff G*mass between semi-interacting and fully interacting massive bodies end subroutine swiftest_io_netcdf_get_valid_masks module subroutine swiftest_io_netcdf_initialize_output(self, param) implicit none - class(swiftest_netcdf_parameters), intent(inout) :: self !! Parameters used to for writing a NetCDF dataset to file - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_netcdf_parameters), intent(inout) :: self + !! Parameters used to for writing a NetCDF dataset to file + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_initialize_output module subroutine swiftest_io_netcdf_open(self, param, readonly) implicit none - class(swiftest_netcdf_parameters), intent(inout) :: self !! Parameters used to identify a particular NetCDF dataset - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - logical, optional, intent(in) :: readonly !! Logical flag indicating that this should be open read only + class(swiftest_netcdf_parameters), intent(inout) :: self + !! Parameters used to identify a particular NetCDF dataset + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + logical, optional, intent(in) :: readonly + !! Logical flag indicating that this should be open read only end subroutine swiftest_io_netcdf_open module function swiftest_io_netcdf_read_frame_system(self, nc, param) result(ierr) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody_system object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to for reading a NetCDF dataset to file - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - integer(I4B) :: ierr !! Error code: returns 0 if the read is successful + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody_system object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to for reading a NetCDF dataset to file + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + integer(I4B) :: ierr + !! Error code: returns 0 if the read is successful end function swiftest_io_netcdf_read_frame_system module subroutine swiftest_io_netcdf_read_hdr_system(self, nc, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to for reading a NetCDF dataset to file - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to for reading a NetCDF dataset to file + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_read_hdr_system module subroutine swiftest_io_netcdf_read_particle_info_system(self, nc, param, plmask, tpmask) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to identify a particular NetCDF dataset - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - logical, dimension(:), intent(in) :: plmask !! Logical array indicating which index values belong to massive bodies - logical, dimension(:), intent(in) :: tpmask !! Logical array indicating which index values belong to test particles + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to identify a particular NetCDF dataset + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + logical, dimension(:), intent(in) :: plmask + !! Logical array indicating which index values belong to massive bodies + logical, dimension(:), intent(in) :: tpmask + !! Logical array indicating which index values belong to test particles end subroutine swiftest_io_netcdf_read_particle_info_system module subroutine swiftest_io_netcdf_write_frame_body(self, nc, param) implicit none - class(swiftest_body), intent(in) :: self !! Swiftest base object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to for writing a NetCDF dataset to file - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_body), intent(in) :: self + !! Swiftest base object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to for writing a NetCDF dataset to file + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_write_frame_body module subroutine swiftest_io_netcdf_write_frame_cb(self, nc, param) implicit none - class(swiftest_cb), intent(inout) :: self !! Swiftest base object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to for writing a NetCDF dataset to file - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_cb), intent(inout) :: self + !! Swiftest base object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to for writing a NetCDF dataset to file + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_write_frame_cb module subroutine swiftest_io_netcdf_write_frame_system(self, nc, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody_system object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to for writing a NetCDF dataset to file - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody_system object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to for writing a NetCDF dataset to file + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_write_frame_system module subroutine swiftest_io_netcdf_write_hdr_system(self, nc, param) implicit none - class(swiftest_nbody_system), intent(in) :: self !! Swiftest nbody system object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to for writing a NetCDF dataset to file - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(in) :: self + !! Swiftest nbody system object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to for writing a NetCDF dataset to file + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_write_hdr_system module subroutine swiftest_io_netcdf_write_info_body(self, nc, param) implicit none - class(swiftest_body), intent(in) :: self !! Swiftest particle object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to identify a particular NetCDF dataset - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_body), intent(in) :: self + !! Swiftest particle object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to identify a particular NetCDF dataset + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_write_info_body module subroutine swiftest_io_netcdf_write_info_cb(self, nc, param) implicit none - class(swiftest_cb), intent(in) :: self !! Swiftest particle object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to identify a particular NetCDF dataset - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_cb), intent(in) :: self + !! Swiftest particle object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to identify a particular NetCDF dataset + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_netcdf_write_info_cb module subroutine swiftest_io_remove_nul_char(string) implicit none - character(len=*), intent(inout) :: string !! String to remove nul characters from + character(len=*), intent(inout) :: string + !! String to remove nul characters from end subroutine swiftest_io_remove_nul_char module subroutine swiftest_io_param_reader(self, unit, iotype, v_list, iostat, iomsg) implicit none - class(swiftest_parameters), intent(inout) :: self !! Collection of parameters - 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. - 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 + class(swiftest_parameters), intent(inout) :: self + !! Collection of parameters + 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. + 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 swiftest_io_param_reader module subroutine swiftest_io_param_writer(self, unit, iotype, v_list, iostat, iomsg) implicit none - class(swiftest_parameters), intent(in) :: self !! Collection of parameters - 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(:) !! Not used in this procedure - integer(I4B), intent(out) :: iostat !! IO status code - character(len=*), intent(inout) :: iomsg !! Message to pass if iostat /= 0 + class(swiftest_parameters), intent(in) :: self + !! Collection of parameters + 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(:) + !! Not used in this procedure + integer(I4B), intent(out) :: iostat + !! IO status code + character(len=*), intent(inout) :: iomsg + !! Message to pass if iostat /= 0 end subroutine swiftest_io_param_writer end interface interface io_param_writer_one module subroutine swiftest_io_param_writer_one_char(param_name, param_value, unit) implicit none - character(len=*), intent(in) :: param_name !! Name of parameter to print - character(len=*), intent(in) :: param_value !! Value of parameter to print - integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to + character(len=*), intent(in) :: param_name + !! Name of parameter to print + character(len=*), intent(in) :: param_value + !! Value of parameter to print + integer(I4B), intent(in) :: unit + !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_char module subroutine swiftest_io_param_writer_one_DP(param_name, param_value, unit) implicit none - character(len=*), intent(in) :: param_name !! Name of parameter to print - real(DP), intent(in) :: param_value !! Value of parameter to print - integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to + character(len=*), intent(in) :: param_name + !! Name of parameter to print + real(DP), intent(in) :: param_value + !! Value of parameter to print + integer(I4B), intent(in) :: unit + !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_DP module subroutine swiftest_io_param_writer_one_DParr(param_name, param_value, unit) implicit none - character(len=*), intent(in) :: param_name !! Name of parameter to print - real(DP), dimension(:), intent(in) :: param_value !! Value of parameter to print - integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to + character(len=*), intent(in) :: param_name + !! Name of parameter to print + real(DP), dimension(:), intent(in) :: param_value + !! Value of parameter to print + integer(I4B), intent(in) :: unit + !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_DParr module subroutine swiftest_io_param_writer_one_I4B(param_name, param_value, unit) implicit none - character(len=*), intent(in) :: param_name !! Name of parameter to print - integer(I4B), intent(in) :: param_value !! Value of parameter to print - integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to + character(len=*), intent(in) :: param_name + !! Name of parameter to print + integer(I4B), intent(in) :: param_value + !! Value of parameter to print + integer(I4B), intent(in) :: unit + !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_I4B module subroutine swiftest_io_param_writer_one_I4Barr(param_name, param_value, unit) implicit none - character(len=*), intent(in) :: param_name !! Name of parameter to print - integer(I4B), dimension(:), intent(in) :: param_value !! Value of parameter to print - integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to + character(len=*), intent(in) :: param_name + !! Name of parameter to print + integer(I4B), dimension(:), intent(in) :: param_value + !! Value of parameter to print + integer(I4B), intent(in) :: unit + !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_I4Barr module subroutine swiftest_io_param_writer_one_I8B(param_name, param_value, unit) implicit none - character(len=*), intent(in) :: param_name !! Name of parameter to print - integer(I8B), intent(in) :: param_value !! Value of parameter to print - integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to + character(len=*), intent(in) :: param_name + !! Name of parameter to print + integer(I8B), intent(in) :: param_value + !! Value of parameter to print + integer(I4B), intent(in) :: unit + !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_I8B module subroutine swiftest_io_param_writer_one_logical(param_name, param_value, unit) implicit none - character(len=*), intent(in) :: param_name !! Name of parameter to print - logical, intent(in) :: param_value !! Value of parameter to print - integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to + character(len=*), intent(in) :: param_name + !! Name of parameter to print + logical, intent(in) :: param_value + !! Value of parameter to print + integer(I4B), intent(in) :: unit + !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_logical #ifdef QUADPREC module subroutine swiftest_io_param_writer_one_QP(param_name, param_value, unit) implicit none - character(len=*), intent(in) :: param_name !! Name of parameter to print - real(QP), intent(in) :: param_value !! Value of parameter to print - integer(I4B), intent(in) :: unit !! Open file unit number to print parameter to + character(len=*), intent(in) :: param_name + !! Name of parameter to print + real(QP), intent(in) :: param_value + !! Value of parameter to print + integer(I4B), intent(in) :: unit + !! Open file unit number to print parameter to end subroutine swiftest_io_param_writer_one_QP #endif end interface io_param_writer_one @@ -899,129 +1341,188 @@ end subroutine swiftest_io_param_writer_one_QP module subroutine swiftest_io_read_in_body(self,param) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest base object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self + !! Swiftest base object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_read_in_body module subroutine swiftest_io_read_in_cb(self,param) implicit none - class(swiftest_cb), intent(inout) :: self !! Swiftest base object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_cb), intent(inout) :: self + !! Swiftest base object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_read_in_cb module subroutine swiftest_io_read_in_param(self, param_file_name) implicit none - class(swiftest_parameters), intent(inout) :: self !! Current run configuration parameters - character(len=*), intent(in) :: param_file_name !! Parameter input file name (i.e. param.in) + class(swiftest_parameters), intent(inout) :: self + !! Current run configuration parameters + character(len=*), intent(in) :: param_file_name + !! Parameter input file name (i.e. param.in) end subroutine swiftest_io_read_in_param module subroutine swiftest_io_read_in_system(self, nc, param) implicit none class(swiftest_nbody_system), intent(inout) :: self - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to identify a particular NetCDF dataset + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to identify a particular NetCDF dataset class(swiftest_parameters), intent(inout) :: param end subroutine swiftest_io_read_in_system module function swiftest_io_read_frame_body(self, iu, param) result(ierr) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - integer(I4B), intent(inout) :: iu !! Unit number for the output file to write frame to - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - integer(I4B) :: ierr !! Error code: returns 0 if the read is successful + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + integer(I4B), intent(inout) :: iu + !! Unit number for the output file to write frame to + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + integer(I4B) :: ierr + !! Error code: returns 0 if the read is successful end function swiftest_io_read_frame_body module function swiftest_io_read_frame_system(self, iu, param) result(ierr) implicit none - class(swiftest_nbody_system),intent(inout) :: self !! Swiftest nbody_system object - integer(I4B), intent(inout) :: iu !! Unit number for the output file to read frame from - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - integer(I4B) :: ierr !! Error code: returns 0 if the read is successful + class(swiftest_nbody_system),intent(inout) :: self + !! Swiftest nbody_system object + integer(I4B), intent(inout) :: iu + !! Unit number for the output file to read frame from + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + integer(I4B) :: ierr + !! Error code: returns 0 if the read is successful end function swiftest_io_read_frame_system module subroutine swiftest_io_set_display_param(self, display_style) implicit none - class(swiftest_parameters), intent(inout) :: self !! Current run configuration parameters - character(*), intent(in) :: display_style !! Style of the output display + class(swiftest_parameters), intent(inout) :: self + !! Current run configuration parameters + character(*), intent(in) :: display_style + !! Style of the output display end subroutine swiftest_io_set_display_param module subroutine swiftest_io_toupper(string) implicit none - character(*), intent(inout) :: string !! String to make upper case + character(*), intent(inout) :: string + !! String to make upper case end subroutine swiftest_io_toupper module subroutine swiftest_io_initialize_output_file_system(self, nc, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody_system object - class(swiftest_netcdf_parameters), intent(inout) :: nc !! Parameters used to identify a particular NetCDF dataset - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody_system object + class(swiftest_netcdf_parameters), intent(inout) :: nc + !! Parameters used to identify a particular NetCDF dataset + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_io_initialize_output_file_system module subroutine swiftest_kick_getacch_int_pl(self, param) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_parameters), intent(inout) :: param !! Current swiftest run configuration parameters + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_parameters), intent(inout) :: param + !! Current swiftest run configuration parameters end subroutine swiftest_kick_getacch_int_pl module subroutine swiftest_kick_getacch_int_tp(self, param, GMpl, rhp, npl) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_parameters), intent(inout) :: param !! Current swiftest run configuration parameters - real(DP), dimension(:), intent(in) :: GMpl !! Massive body masses - real(DP), dimension(:,:), intent(in) :: rhp !! Massive body position vectors - integer(I4B), intent(in) :: npl !! Number of active massive bodies + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_parameters), intent(inout) :: param + !! Current swiftest run configuration parameters + real(DP), dimension(:), intent(in) :: GMpl + !! Massive body masses + real(DP), dimension(:,:), intent(in) :: rhp + !! Massive body position vectors + integer(I4B), intent(in) :: npl + !! Number of active massive bodies end subroutine swiftest_kick_getacch_int_tp end interface interface swiftest_kick_getacch_int_all module subroutine swiftest_kick_getacch_int_all_flat_rad_pl(npl, nplpl, k_plpl, r, Gmass, radius, acc) implicit none - integer(I4B), intent(in) :: npl !! Number of massive bodies - integer(I8B), intent(in) :: nplpl !! Number of massive body interactions to compute - integer(I4B), dimension(:,:), intent(in) :: k_plpl !! Array of interaction pair indices (flattened upper triangular matrix) - real(DP), dimension(:,:), intent(in) :: r !! Position vector array - real(DP), dimension(:), intent(in) :: Gmass !! Array of massive body G*mass - real(DP), dimension(:), intent(in) :: radius !! Array of massive body radii - real(DP), dimension(:,:), intent(inout) :: acc !! Acceleration vector array + integer(I4B), intent(in) :: npl + !! Number of massive bodies + integer(I8B), intent(in) :: nplpl + !! Number of massive body interactions to compute + integer(I4B), dimension(:,:), intent(in) :: k_plpl + !! Array of interaction pair indices (flattened upper triangular matrix) + real(DP), dimension(:,:), intent(in) :: r + !! Position vector array + real(DP), dimension(:), intent(in) :: Gmass + !! Array of massive body G*mass + real(DP), dimension(:), intent(in) :: radius + !! Array of massive body radii + real(DP), dimension(:,:), intent(inout) :: acc + !! Acceleration vector array end subroutine swiftest_kick_getacch_int_all_flat_rad_pl module subroutine swiftest_kick_getacch_int_all_flat_norad_pl(npl, nplpl, k_plpl, r, Gmass, acc) implicit none - integer(I4B), intent(in) :: npl !! Number of massive bodies - integer(I8B), intent(in) :: nplpl !! Number of massive body interactions to compute - integer(I4B), dimension(:,:), intent(in) :: k_plpl !! Array of interaction pair indices (flattened upper triangular matrix) - real(DP), dimension(:,:), intent(in) :: r !! Position vector array - real(DP), dimension(:), intent(in) :: Gmass !! Array of massive body G*mass - real(DP), dimension(:,:), intent(inout) :: acc !! Acceleration vector array + integer(I4B), intent(in) :: npl + !! Number of massive bodies + integer(I8B), intent(in) :: nplpl + !! Number of massive body interactions to compute + integer(I4B), dimension(:,:), intent(in) :: k_plpl + !! Array of interaction pair indices (flattened upper triangular matrix) + real(DP), dimension(:,:), intent(in) :: r + !! Position vector array + real(DP), dimension(:), intent(in) :: Gmass + !! Array of massive body G*mass + real(DP), dimension(:,:), intent(inout) :: acc + !! Acceleration vector array end subroutine swiftest_kick_getacch_int_all_flat_norad_pl module subroutine swiftest_kick_getacch_int_all_tri_rad_pl(npl, nplm, r, Gmass, radius, acc) implicit none - integer(I4B), intent(in) :: npl !! Total number of massive bodies - integer(I4B), intent(in) :: nplm !! Number of fully interacting massive bodies - real(DP), dimension(:,:), intent(in) :: r !! Position vector array - real(DP), dimension(:), intent(in) :: Gmass !! Array of massive body G*mass - real(DP), dimension(:), intent(in) :: radius !! Array of massive body radii - real(DP), dimension(:,:), intent(inout) :: acc !! Acceleration vector array + integer(I4B), intent(in) :: npl + !! Total number of massive bodies + integer(I4B), intent(in) :: nplm + !! Number of fully interacting massive bodies + real(DP), dimension(:,:), intent(in) :: r + !! Position vector array + real(DP), dimension(:), intent(in) :: Gmass + !! Array of massive body G*mass + real(DP), dimension(:), intent(in) :: radius + !! Array of massive body radii + real(DP), dimension(:,:), intent(inout) :: acc + !! Acceleration vector array end subroutine swiftest_kick_getacch_int_all_tri_rad_pl module subroutine swiftest_kick_getacch_int_all_tri_norad_pl(npl, nplm, r, Gmass, acc) implicit none - integer(I4B), intent(in) :: npl !! Total number of massive bodies - integer(I4B), intent(in) :: nplm !! Number of fully interacting massive bodies - real(DP), dimension(:,:), intent(in) :: r !! Position vector array - real(DP), dimension(:), intent(in) :: Gmass !! Array of massive body G*mass - real(DP), dimension(:,:), intent(inout) :: acc !! Acceleration vector array + integer(I4B), intent(in) :: npl + !! Total number of massive bodies + integer(I4B), intent(in) :: nplm + !! Number of fully interacting massive bodies + real(DP), dimension(:,:), intent(in) :: r + !! Position vector array + real(DP), dimension(:), intent(in) :: Gmass + !! Array of massive body G*mass + real(DP), dimension(:,:), intent(inout) :: acc + !! Acceleration vector array end subroutine swiftest_kick_getacch_int_all_tri_norad_pl module subroutine swiftest_kick_getacch_int_all_tp(ntp, npl, rtp, rpl, GMpl, lmask, acc) implicit none - integer(I4B), intent(in) :: ntp !! Number of test particles - integer(I4B), intent(in) :: npl !! Number of massive bodies - real(DP), dimension(:,:), intent(in) :: rtp !! Test particle position vector array - real(DP), dimension(:,:), intent(in) :: rpl !! Massive body particle position vector array - real(DP), dimension(:), intent(in) :: GMpl !! Array of massive body G*mass - logical, dimension(:), intent(in) :: lmask !! Logical mask indicating which test particles should be computed - real(DP), dimension(:,:), intent(inout) :: acc !! Acceleration vector array + integer(I4B), intent(in) :: ntp + !! Number of test particles + integer(I4B), intent(in) :: npl + !! Number of massive bodies + real(DP), dimension(:,:), intent(in) :: rtp + !! Test particle position vector array + real(DP), dimension(:,:), intent(in) :: rpl + !! Massive body particle position vector array + real(DP), dimension(:), intent(in) :: GMpl + !! Array of massive body G*mass + logical, dimension(:), intent(in) :: lmask + !! Logical mask indicating which test particles should be computed + real(DP), dimension(:,:), intent(inout) :: acc + !! Acceleration vector array end subroutine swiftest_kick_getacch_int_all_tp end interface @@ -1029,66 +1530,97 @@ end subroutine swiftest_kick_getacch_int_all_tp pure module subroutine swiftest_kick_getacch_int_one_pl(rji2, xr, yr, zr, Gmi, Gmj, axi, ayi, azi, axj, ayj, azj) !$omp declare simd(swiftest_kick_getacch_int_one_pl) implicit none - real(DP), intent(in) :: rji2 !! Square of distance between the two bodies - real(DP), intent(in) :: xr, yr, zr !! Distances between the two bodies in x, y, and z directions - real(DP), intent(in) :: Gmi !! G*mass of body i - real(DP), intent(in) :: Gmj !! G*mass of body j - real(DP), intent(inout) :: axi, ayi, azi !! Acceleration vector components of body i - real(DP), intent(inout) :: axj, ayj, azj !! Acceleration vector components of body j + real(DP), intent(in) :: rji2 + !! Square of distance between the two bodies + real(DP), intent(in) :: xr, yr, zr + !! Distances between the two bodies in x, y, and z directions + real(DP), intent(in) :: Gmi + !! G*mass of body i + real(DP), intent(in) :: Gmj + !! G*mass of body j + real(DP), intent(inout) :: axi, ayi, azi + !! Acceleration vector components of body i + real(DP), intent(inout) :: axj, ayj, azj + !! Acceleration vector components of body j end subroutine swiftest_kick_getacch_int_one_pl pure module subroutine swiftest_kick_getacch_int_one_tp(rji2, xr, yr, zr, Gmpl, ax, ay, az) !$omp declare simd(swiftest_kick_getacch_int_one_tp) implicit none - real(DP), intent(in) :: rji2 !! Square of distance between the test particle and massive body - real(DP), intent(in) :: xr, yr, zr !! Distances between the two bodies in x, y, and z directions - real(DP), intent(in) :: Gmpl !! G*mass of massive body - real(DP), intent(inout) :: ax, ay, az !! Acceleration vector components of test particle + real(DP), intent(in) :: rji2 + !! Square of distance between the test particle and massive body + real(DP), intent(in) :: xr, yr, zr + !! Distances between the two bodies in x, y, and z directions + real(DP), intent(in) :: Gmpl + !! G*mass of massive body + real(DP), intent(inout) :: ax, ay, az + !! Acceleration vector components of test particle end subroutine swiftest_kick_getacch_int_one_tp module subroutine swiftest_obl_rot_matrix(n, rot, rot_matrix, rot_matrix_inv) implicit none - integer(I4B), intent(in) :: n !! Number of bodies - real(DP), dimension(NDIM), intent(in) :: rot !! Central body rotation vector - real(DP), dimension(NDIM, NDIM), intent(inout) :: rot_matrix !! rotation matrix - real(DP), dimension(NDIM, NDIM), intent(inout) :: rot_matrix_inv !! inverse of the rotation matrix + integer(I4B), intent(in) :: n + !! Number of bodies + real(DP), dimension(NDIM), intent(in) :: rot + !! Central body rotation vector + real(DP), dimension(NDIM, NDIM), intent(inout) :: rot_matrix + !! rotation matrix + real(DP), dimension(NDIM, NDIM), intent(inout) :: rot_matrix_inv + !! inverse of the rotation matrix end subroutine swiftest_obl_rot_matrix module subroutine swiftest_obl_acc(n, GMcb, j2rp2, j4rp4, rh, lmask, aobl, rot, GMpl, aoblcb) implicit none - integer(I4B), intent(in) :: n !! Number of bodies - real(DP), intent(in) :: GMcb !! Central body G*Mass - real(DP), intent(in) :: j2rp2 !! J2 * R**2 for the central body - real(DP), intent(in) :: j4rp4 !! J4 * R**4 for the central body - real(DP), dimension(:,:), intent(in) :: rh !! Heliocentric positions of bodies - logical, dimension(:), intent(in) :: lmask !! Logical mask of bodies to compute aobl - real(DP), dimension(:,:), intent(out) :: aobl !! Barycentric acceleration of bodies due to central body oblateness - real(DP), dimension(NDIM), intent(in) :: rot !! Central body rotation matrix - real(DP), dimension(:), intent(in), optional :: GMpl !! Masses of input bodies if they are not test particles - real(DP), dimension(:), intent(out), optional :: aoblcb !! Barycentric acceleration of central body (only needed if input bodies are massive) + integer(I4B), intent(in) :: n + !! Number of bodies + real(DP), intent(in) :: GMcb + !! Central body G*Mass + real(DP), intent(in) :: j2rp2 + !! J2 * R**2 for the central body + real(DP), intent(in) :: j4rp4 + !! J4 * R**4 for the central body + real(DP), dimension(:,:), intent(in) :: rh + !! Heliocentric positions of bodies + logical, dimension(:), intent(in) :: lmask + !! Logical mask of bodies to compute aobl + real(DP), dimension(:,:), intent(out) :: aobl + !! Barycentric acceleration of bodies due to central body oblateness + real(DP), dimension(NDIM), intent(in) :: rot + !! Central body rotation matrix + real(DP), dimension(:), intent(in), optional :: GMpl + !! Masses of input bodies if they are not test particles + real(DP), dimension(:), intent(out), optional :: aoblcb + !! Barycentric acceleration of central body (only needed if input bodies are massive) end subroutine swiftest_obl_acc - module subroutine swiftest_obl_acc_pl(self, nbody_system) + module subroutine swiftest_non_spherical_cb_acc_pl(self, nbody_system) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - end subroutine swiftest_obl_acc_pl + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + end subroutine swiftest_non_spherical_cb_acc_pl - module subroutine swiftest_obl_acc_tp(self, nbody_system) + module subroutine swiftest_non_spherical_cb_acc_tp(self, nbody_system) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - end subroutine swiftest_obl_acc_tp + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + end subroutine swiftest_non_spherical_cb_acc_tp module subroutine swiftest_obl_pot_system(self) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object end subroutine swiftest_obl_pot_system module subroutine swiftest_orbel_el2xv_vec(self, cb) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_orbel_el2xv_vec pure module subroutine swiftest_orbel_scget(angle, sx, cx) @@ -1101,198 +1633,288 @@ end subroutine swiftest_orbel_scget pure elemental module subroutine swiftest_orbel_xv2aeq(mu, rx, ry, rz, vx, vy, vz, a, e, q) !$omp declare simd(swiftest_orbel_xv2aeq) implicit none - real(DP), intent(in) :: mu !! Gravitational constant - real(DP), intent(in) :: rx,ry,rz !! Position vector - real(DP), intent(in) :: vx,vy,vz !! Velocity vector - real(DP), intent(out) :: a !! semimajor axis - real(DP), intent(out) :: e !! eccentricity - real(DP), intent(out) :: q !! periapsis + real(DP), intent(in) :: mu + !! Gravitational constant + real(DP), intent(in) :: rx,ry,rz + !! Position vector + real(DP), intent(in) :: vx,vy,vz + !! Velocity vector + real(DP), intent(out) :: a + !! semimajor axis + real(DP), intent(out) :: e + !! eccentricity + real(DP), intent(out) :: q + !! periapsis end subroutine swiftest_orbel_xv2aeq pure module subroutine swiftest_orbel_xv2aqt(mu, rx, ry, rz, vx, vy, vz, a, q, capm, tperi) !$omp declare simd(swiftest_orbel_xv2aqt) implicit none - real(DP), intent(in) :: mu !! Gravitational constant - real(DP), intent(in) :: rx,ry,rz !! Position vector - real(DP), intent(in) :: vx,vy,vz !! Velocity vector - real(DP), intent(out) :: a !! semimajor axis - real(DP), intent(out) :: q !! periapsis - real(DP), intent(out) :: capm !! mean anomaly - real(DP), intent(out) :: tperi !! time of pericenter passage + real(DP), intent(in) :: mu + !! Gravitational constant + real(DP), intent(in) :: rx,ry,rz + !! Position vector + real(DP), intent(in) :: vx,vy,vz + !! Velocity vector + real(DP), intent(out) :: a + !! semimajor axis + real(DP), intent(out) :: q + !! periapsis + real(DP), intent(out) :: capm + !! mean anomaly + real(DP), intent(out) :: tperi + !! time of pericenter passage end subroutine swiftest_orbel_xv2aqt - pure module subroutine swiftest_orbel_xv2el(mu, rx, ry, rz, vx, vy, vz, a, e, inc, capom, omega, capm, varpi, lam, f, cape, capf) - implicit none - real(DP), intent(in) :: mu !! Gravitational constant - real(DP), intent(in) :: rx,ry,rz !! Position vector - real(DP), intent(in) :: vx,vy,vz !! Velocity vector - real(DP), intent(out) :: a !! semimajor axis - real(DP), intent(out) :: e !! eccentricity - real(DP), intent(out) :: inc !! inclination - real(DP), intent(out) :: capom !! longitude of ascending node - real(DP), intent(out) :: omega !! argument of periapsis - real(DP), intent(out) :: capm !! mean anomaly - real(DP), intent(out) :: varpi !! longitude of periapsis - real(DP), intent(out) :: lam !! mean longitude - real(DP), intent(out) :: f !! true anomaly - real(DP), intent(out) :: cape !! eccentric anomaly (eccentric orbits) - real(DP), intent(out) :: capf !! hyperbolic anomaly (hyperbolic orbits) + pure module subroutine swiftest_orbel_xv2el(mu, rx, ry, rz, vx, vy, vz, & + a, e, inc, capom, omega, capm, varpi, lam, f, cape, capf) + implicit none + real(DP), intent(in) :: mu + !! Gravitational constant + real(DP), intent(in) :: rx,ry,rz + !! Position vector + real(DP), intent(in) :: vx,vy,vz + !! Velocity vector + real(DP), intent(out) :: a + !! semimajor axis + real(DP), intent(out) :: e + !! eccentricity + real(DP), intent(out) :: inc + !! inclination + real(DP), intent(out) :: capom + !! longitude of ascending node + real(DP), intent(out) :: omega + !! argument of periapsis + real(DP), intent(out) :: capm + !! mean anomaly + real(DP), intent(out) :: varpi + !! longitude of periapsis + real(DP), intent(out) :: lam + !! mean longitude + real(DP), intent(out) :: f + !! true anomaly + real(DP), intent(out) :: cape + !! eccentric anomaly (eccentric orbits) + real(DP), intent(out) :: capf + !! hyperbolic anomaly (hyperbolic orbits) end subroutine swiftest_orbel_xv2el module subroutine swiftest_orbel_xv2el_vec(self, cb) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_orbel_xv2el_vec module subroutine swiftest_util_setup_body(self, n, param) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - integer(I4B), intent(in) :: n !! Number of particles to allocate space for - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + integer(I4B), intent(in) :: n + !! Number of particles to allocate space for + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_util_setup_body module subroutine swiftest_util_setup_construct_system(nbody_system, param) implicit none - class(swiftest_nbody_system), allocatable, intent(inout) :: nbody_system !! Swiftest nbody_system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), allocatable, intent(inout) :: nbody_system + !! Swiftest nbody_system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_util_setup_construct_system module subroutine swiftest_util_setup_initialize_particle_info_system(self, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_util_setup_initialize_particle_info_system module subroutine swiftest_util_setup_initialize_system(self, system_history, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody_system object - class(swiftest_storage), allocatable, intent(inout) :: system_history !! Stores the system history between output dumps - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody_system object + class(swiftest_storage), allocatable, intent(inout) :: system_history + !! Stores the system history between output dumps + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_util_setup_initialize_system module subroutine swiftest_util_setup_pl(self, n, param) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - integer(I4B), intent(in) :: n !! Number of particles to allocate space for - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + integer(I4B), intent(in) :: n + !! Number of particles to allocate space for + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_util_setup_pl module subroutine swiftest_util_setup_tp(self, n, param) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - integer(I4B), intent(in) :: n !! Number of particles to allocate space for - class(swiftest_parameters), intent(in) :: param !! Current run configuration parametersr + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + integer(I4B), intent(in) :: n + !! Number of particles to allocate space for + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parametersr end subroutine swiftest_util_setup_tp module subroutine swiftest_user_kick_getacch_body(self, nbody_system, param, t, lbeg) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest massive body particle data structure - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody_system_object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! Current time - logical, intent(in) :: lbeg !! Optional argument that determines whether or not this is the beginning or end of the step + class(swiftest_body), intent(inout) :: self + !! Swiftest massive body particle data structure + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody_system_object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + real(DP), intent(in) :: t + !! Current time + logical, intent(in) :: lbeg + !! Optional argument that determines whether or not this is the beginning or end of the step end subroutine swiftest_user_kick_getacch_body end interface interface util_append module subroutine swiftest_util_append_arr_info(arr, source, nold, lsource_mask) implicit none - type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: arr !! Destination array - type(swiftest_particle_info), dimension(:), allocatable, intent(in) :: source !! Array to append - integer(I4B), intent(in), optional :: nold !! Extent of original array. If passed, the source array will begin at arr(nold+1). Otherwise, the size of arr will be used. - logical, dimension(:), intent(in), optional :: lsource_mask !! Logical mask indicating which elements to append to + type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + type(swiftest_particle_info), dimension(:), allocatable, intent(in) :: source + !! Array to append + integer(I4B), intent(in), optional :: nold + !! Extent of original array. If passed, the source array will begin at arr(nold+1). + !! Otherwise, the size of arr will be used. + logical, dimension(:), intent(in), optional :: lsource_mask + !! Logical mask indicating which elements to append to end subroutine swiftest_util_append_arr_info module subroutine swiftest_util_append_arr_kin(arr, source, nold, lsource_mask) implicit none - type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: arr !! Destination array - type(swiftest_kinship), dimension(:), allocatable, intent(in) :: source !! Array to append - integer(I4B), intent(in), optional :: nold !! Extent of original array. If passed, the source array will begin at arr(nold+1). Otherwise, the size of arr will be used. - logical, dimension(:), intent(in), optional :: lsource_mask !! Logical mask indicating which elements to append to + type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + type(swiftest_kinship), dimension(:), allocatable, intent(in) :: source + !! Array to append + integer(I4B), intent(in), optional :: nold + !! Extent of original array. If passed, the source array will begin at arr(nold+1). + !! Otherwise, the size of arr will be used. + logical, dimension(:), intent(in), optional :: lsource_mask + !! Logical mask indicating which elements to append to end subroutine swiftest_util_append_arr_kin end interface interface module subroutine swiftest_util_append_body(self, source, lsource_mask) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(in) :: source !! Source object to append - logical, dimension(:), intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + class(swiftest_body), intent(in) :: source + !! Source object to append + logical, dimension(:), intent(in) :: lsource_mask + !! Logical mask indicating which elements to append to end subroutine swiftest_util_append_body module subroutine swiftest_util_append_pl(self, source, lsource_mask) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_body), intent(in) :: source !! Source object to append - logical, dimension(:), intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_body), intent(in) :: source + !! Source object to append + logical, dimension(:), intent(in) :: lsource_mask + !! Logical mask indicating which elements to append to end subroutine swiftest_util_append_pl module subroutine swiftest_util_append_tp(self, source, lsource_mask) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_body), intent(in) :: source !! Source object to append - logical, dimension(:), intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_body), intent(in) :: source + !! Source object to append + logical, dimension(:), intent(in) :: lsource_mask + !! Logical mask indicating which elements to append to end subroutine swiftest_util_append_tp module subroutine swiftest_util_coord_b2h_pl(self, cb) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_coord_b2h_pl module subroutine swiftest_util_coord_b2h_tp(self, cb) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_cb), intent(in) :: cb !! Swiftest central body object + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_cb), intent(in) :: cb + !! Swiftest central body object end subroutine swiftest_util_coord_b2h_tp module subroutine swiftest_util_coord_h2b_pl(self, cb) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_coord_h2b_pl module subroutine swiftest_util_coord_h2b_tp(self, cb) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_cb), intent(in) :: cb !! Swiftest central body object + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_cb), intent(in) :: cb + !! Swiftest central body object end subroutine swiftest_util_coord_h2b_tp module subroutine swiftest_util_coord_vb2vh_pl(self, cb) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_coord_vb2vh_pl module subroutine swiftest_util_coord_vb2vh_tp(self, vbcb) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - real(DP), dimension(:), intent(in) :: vbcb !! Barycentric velocity of the central body + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + real(DP), dimension(:), intent(in) :: vbcb + !! Barycentric velocity of the central body end subroutine swiftest_util_coord_vb2vh_tp module subroutine swiftest_util_coord_vh2vb_pl(self, cb) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_coord_vh2vb_pl module subroutine swiftest_util_coord_vh2vb_tp(self, vbcb) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - real(DP), dimension(:), intent(in) :: vbcb !! Barycentric velocity of the central body + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + real(DP), dimension(:), intent(in) :: vbcb + !! Barycentric velocity of the central body end subroutine swiftest_util_coord_vh2vb_tp module subroutine swiftest_util_coord_rh2rb_pl(self, cb) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_coord_rh2rb_pl module subroutine swiftest_util_coord_rh2rb_tp(self, cb) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_cb), intent(in) :: cb !! Swiftest central body object + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_cb), intent(in) :: cb + !! Swiftest central body object end subroutine swiftest_util_coord_rh2rb_tp module subroutine swiftest_util_copy_particle_info(self, source) @@ -1303,9 +1925,12 @@ end subroutine swiftest_util_copy_particle_info module subroutine swiftest_util_copy_particle_info_arr(source, dest, idx) implicit none - class(swiftest_particle_info), dimension(:), intent(in) :: source !! Source object to copy into - class(swiftest_particle_info), dimension(:), intent(inout) :: dest !! Swiftest body object with particle metadata information object - integer(I4B), dimension(:), intent(in), optional :: idx !! Optional array of indices to draw the source object + class(swiftest_particle_info), dimension(:), intent(in) :: source + !! Source object to copy into + class(swiftest_particle_info), dimension(:), intent(inout) :: dest + !! Swiftest body object with particle metadata information object + integer(I4B), dimension(:), intent(in), optional :: idx + !! Optional array of indices to draw the source object end subroutine swiftest_util_copy_particle_info_arr module subroutine swiftest_util_dealloc_body(self) @@ -1315,12 +1940,14 @@ end subroutine swiftest_util_dealloc_body module subroutine swiftest_util_dealloc_kin(self) implicit none - class(swiftest_kinship), intent(inout) :: self !! Swiftest kinship object + class(swiftest_kinship), intent(inout) :: self + !! Swiftest kinship object end subroutine swiftest_util_dealloc_kin module subroutine swiftest_util_dealloc_cb(self) implicit none - class(swiftest_cb), intent(inout) :: self !! Swiftest central body object + class(swiftest_cb), intent(inout) :: self + !! Swiftest central body object end subroutine swiftest_util_dealloc_cb module subroutine swiftest_util_dealloc_pl(self) @@ -1330,7 +1957,8 @@ end subroutine swiftest_util_dealloc_pl module subroutine swiftest_util_dealloc_storage(self) implicit none - class(swiftest_storage), intent(inout) :: self !! Swiftest storage object + class(swiftest_storage), intent(inout) :: self + !! Swiftest storage object end subroutine swiftest_util_dealloc_storage module subroutine swiftest_util_dealloc_system(self) @@ -1345,39 +1973,54 @@ end subroutine swiftest_util_dealloc_tp module subroutine swiftest_util_fill_body(self, inserts, lfill_list) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(in) :: inserts !! Swiftest body object to be inserted - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + class(swiftest_body), intent(in) :: inserts + !! Swiftest body object to be inserted + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps end subroutine swiftest_util_fill_body module subroutine swiftest_util_fill_pl(self, inserts, lfill_list) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_body), intent(in) :: inserts !! Swiftest body object to be inserted - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_body), intent(in) :: inserts + !! Swiftest body object to be inserted + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps end subroutine swiftest_util_fill_pl module subroutine swiftest_util_fill_tp(self, inserts, lfill_list) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_body), intent(in) :: inserts !! Swiftest body object to be inserted - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_body), intent(in) :: inserts + !! Swiftest body object to be inserted + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps end subroutine swiftest_util_fill_tp end interface interface util_fill module subroutine swiftest_util_fill_arr_info(keeps, inserts, lfill_list) implicit none - type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - type(swiftest_particle_info), dimension(:), allocatable, intent(in) :: inserts !! Array of values to insert into keep - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + type(swiftest_particle_info), dimension(:), allocatable, intent(in) :: inserts + !! Array of values to insert into keep + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps end subroutine swiftest_util_fill_arr_info module subroutine swiftest_util_fill_arr_kin(keeps, inserts, lfill_list) implicit none - type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - type(swiftest_kinship), dimension(:), allocatable, intent(in) :: inserts !! Array of values to insert into keep - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + type(swiftest_kinship), dimension(:), allocatable, intent(in) :: inserts + !! Array of values to insert into keep + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps end subroutine swiftest_util_fill_arr_kin end interface @@ -1385,43 +2028,60 @@ end subroutine swiftest_util_fill_arr_kin pure module subroutine swiftest_util_flatten_eucl_ij_to_k(n, i, j, k) !$omp declare simd(swiftest_util_flatten_eucl_ij_to_k) implicit none - integer(I4B), intent(in) :: n !! Number of bodies - integer(I4B), intent(in) :: i !! Index of the ith body - integer(I4B), intent(in) :: j !! Index of the jth body - integer(I8B), intent(out) :: k !! Index of the flattened matrix + integer(I4B), intent(in) :: n + !! Number of bodies + integer(I4B), intent(in) :: i + !! Index of the ith body + integer(I4B), intent(in) :: j + !! Index of the jth body + integer(I8B), intent(out) :: k + !! Index of the flattened matrix end subroutine swiftest_util_flatten_eucl_ij_to_k pure module subroutine swiftest_util_flatten_eucl_k_to_ij(n, k, i, j) implicit none - integer(I4B), intent(in) :: n !! Number of bodies - integer(I8B), intent(in) :: k !! Index of the flattened matrix - integer(I4B), intent(out) :: i !! Index of the ith body - integer(I4B), intent(out) :: j !! Index of the jth body + integer(I4B), intent(in) :: n + !! Number of bodies + integer(I8B), intent(in) :: k + !! Index of the flattened matrix + integer(I4B), intent(out) :: i + !! Index of the ith body + integer(I4B), intent(out) :: j + !! Index of the jth body end subroutine swiftest_util_flatten_eucl_k_to_ij module subroutine swiftest_util_flatten_eucl_plpl(self, param) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine module subroutine swiftest_util_flatten_eucl_pltp(self, pl, param) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_pl), intent(in) :: pl !! Swiftest massive body object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_pl), intent(in) :: pl + !! Swiftest massive body object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine module subroutine swiftest_util_get_energy_and_momentum_system(self, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_util_get_energy_and_momentum_system module subroutine swiftest_util_get_idvalues_system(self, idvals) implicit none - class(swiftest_nbody_system), intent(in) :: self !! Encounter snapshot object - integer(I4B), dimension(:), allocatable, intent(out) :: idvals !! Array of all id values saved in this snapshot + class(swiftest_nbody_system), intent(in) :: self + !! Encounter snapshot object + integer(I4B), dimension(:), allocatable, intent(out) :: idvals + !! Array of all id values saved in this snapshot end subroutine swiftest_util_get_idvalues_system end interface @@ -1453,78 +2113,111 @@ end subroutine swiftest_util_get_potential_energy_triangular interface module subroutine swiftest_util_get_vals_storage(self, idvals, tvals) - class(swiftest_storage), intent(in) :: self !! Swiftest storage object - integer(I4B), dimension(:), allocatable, intent(out) :: idvals !! Array of all id values in all snapshots - real(DP), dimension(:), allocatable, intent(out) :: tvals !! Array of all time values in all snapshots + class(swiftest_storage), intent(in) :: self + !! Swiftest storage object + integer(I4B), dimension(:), allocatable, intent(out) :: idvals + !! Array of all id values in all snapshots + real(DP), dimension(:), allocatable, intent(out) :: tvals + !! Array of all time values in all snapshots end subroutine swiftest_util_get_vals_storage module subroutine swiftest_util_index_array(ind_arr, n) implicit none - integer(I4B), dimension(:), allocatable, intent(inout) :: ind_arr !! Index array. Input is a pre-existing index array where n /= size(ind_arr). Output is a new index array ind_arr = [1, 2, ... n] - integer(I4B), intent(in) :: n !! The new size of the index array + integer(I4B), dimension(:), allocatable, intent(inout) :: ind_arr + !! Index array. Input is a pre-existing index array where n /= size(ind_arr). + !! Output is a new index array ind_arr = [1, 2, ... n] + integer(I4B), intent(in) :: n + !! The new size of the index array end subroutine swiftest_util_index_array module subroutine swiftest_util_index_map_storage(self) implicit none - class(swiftest_storage), intent(inout) :: self !! Swiftest storage object + class(swiftest_storage), intent(inout) :: self + !! Swiftest storage object end subroutine swiftest_util_index_map_storage module subroutine swiftest_util_make_impactors_pl(self, idx) implicit none - class(swiftest_pl), intent(inout) :: self !! Massive body object - integer(I4B), dimension(:), intent(in) :: idx !! Array holding the indices of the two bodies involved in the collision) + class(swiftest_pl), intent(inout) :: self + !! Massive body object + integer(I4B), dimension(:), intent(in) :: idx + !! Array holding the indices of the two bodies involved in the collision) end subroutine swiftest_util_make_impactors_pl module subroutine swiftest_util_peri(n,m, r, v, atp, q, isperi) implicit none - integer(I4B), intent(in) :: n !! Number of bodies - real(DP), dimension(:), intent(in) :: m !! Mass term (mu for HELIO coordinates, and Gmtot for BARY) - real(DP), dimension(:,:), intent(in) :: r !! Position vectors (rh for HELIO coordinates, rb for BARY) - real(DP), dimension(:,:), intent(in) :: v !! Position vectors (vh for HELIO coordinates, rb for BARY) - real(DP), dimension(:), intent(out) :: atp !! Semimajor axis - real(DP), dimension(:), intent(out) :: q !! Periapsis - integer(I4B), dimension(:), intent(inout) :: isperi !! Periapsis passage flag + integer(I4B), intent(in) :: n + !! Number of bodies + real(DP), dimension(:), intent(in) :: m + !! Mass term (mu for HELIO coordinates, and Gmtot for BARY) + real(DP), dimension(:,:), intent(in) :: r + !! Position vectors (rh for HELIO coordinates, rb for BARY) + real(DP), dimension(:,:), intent(in) :: v + !! Position vectors (vh for HELIO coordinates, rb for BARY) + real(DP), dimension(:), intent(out) :: atp + !! Semimajor axis + real(DP), dimension(:), intent(out) :: q + !! Periapsis + integer(I4B), dimension(:), intent(inout) :: isperi + !! Periapsis passage flag end subroutine swiftest_util_peri module subroutine swiftest_util_peri_body(self, nbody_system, param) implicit none - class(swiftest_body), intent(inout) :: self !! SyMBA massive body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self + !! SyMBA massive body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_util_peri_body module subroutine swiftest_util_peri_tp(self, nbody_system, param) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameters end subroutine swiftest_util_peri_tp module subroutine swiftest_util_rearray_pl(self, nbody_system, param) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_util_rearray_pl module subroutine swiftest_util_rearray_tp(self, nbody_system, param) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_util_rearray_tp module subroutine swiftest_util_rescale_system(self, param, mscale, dscale, tscale) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters. Returns with new values of the scale vactors and GU - real(DP), intent(in) :: mscale, dscale, tscale !! Scale factors for mass, distance, and time units, respectively. + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters. Returns with new values of the scale vactors and GU + real(DP), intent(in) :: mscale, dscale, tscale + !! Scale factors for mass, distance, and time units, respectively. end subroutine swiftest_util_rescale_system module subroutine swiftest_util_reset_kinship_pl(self, idx) implicit none - class(swiftest_pl), intent(inout) :: self !! SyMBA massive body object - integer(I4B), dimension(:), intent(in) :: idx !! Index array of bodies to reset + class(swiftest_pl), intent(inout) :: self + !! SyMBA massive body object + integer(I4B), dimension(:), intent(in) :: idx + !! Index array of bodies to reset end subroutine swiftest_util_reset_kinship_pl end interface @@ -1533,130 +2226,180 @@ end subroutine swiftest_util_reset_kinship_pl interface util_resize module subroutine swiftest_util_resize_arr_info(arr, nnew) implicit none - type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: arr !! Array to resize - integer(I4B), intent(in) :: nnew !! New size + type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: arr + !! Array to resize + integer(I4B), intent(in) :: nnew + !! New size end subroutine swiftest_util_resize_arr_info module subroutine swiftest_util_resize_arr_kin(arr, nnew) implicit none - type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: arr !! Array to resize - integer(I4B), intent(in) :: nnew !! New size + type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: arr + !! Array to resize + integer(I4B), intent(in) :: nnew + !! New size end subroutine swiftest_util_resize_arr_kin end interface interface module subroutine swiftest_util_resize_body(self, nnew) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - integer(I4B), intent(in) :: nnew !! New size neded + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + integer(I4B), intent(in) :: nnew + !! New size neded end subroutine swiftest_util_resize_body module subroutine swiftest_util_resize_pl(self, nnew) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - integer(I4B), intent(in) :: nnew !! New size neded + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + integer(I4B), intent(in) :: nnew + !! New size neded end subroutine swiftest_util_resize_pl module subroutine swiftest_util_resize_storage(storage, nold, nnew) use base, only : base_storage implicit none - class(base_storage), allocatable, intent(inout) :: storage !! Original storage object - integer(I4B), intent(in) :: nold !! Old size - integer(I4B), intent(in) :: nnew !! New size + class(base_storage), allocatable, intent(inout) :: storage + !! Original storage object + integer(I4B), intent(in) :: nold + !! Old size + integer(I4B), intent(in) :: nnew + !! New size end subroutine swiftest_util_resize_storage module subroutine swiftest_util_resize_tp(self, nnew) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - integer(I4B), intent(in) :: nnew !! New size neded + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + integer(I4B), intent(in) :: nnew + !! New size neded end subroutine swiftest_util_resize_tp module subroutine swiftest_util_set_beg_end_pl(self, rbeg, rend, vbeg) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - real(DP), dimension(:,:), intent(in), optional :: rbeg !! Position vectors at beginning of step - real(DP), dimension(:,:), intent(in), optional :: rend !! Positions vectors at end of step - real(DP), dimension(:,:), intent(in), optional :: vbeg !! vbeg is an unused variable to keep this method forward compatible with RMVS + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + real(DP), dimension(:,:), intent(in), optional :: rbeg + !! Position vectors at beginning of step + real(DP), dimension(:,:), intent(in), optional :: rend + !! Positions vectors at end of step + real(DP), dimension(:,:), intent(in), optional :: vbeg + !! vbeg is an unused variable to keep this method forward compatible with RMVS end subroutine swiftest_util_set_beg_end_pl module subroutine swiftest_util_set_ir3h(self) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object + class(swiftest_body), intent(inout) :: self + !! Swiftest body object end subroutine swiftest_util_set_ir3h module subroutine swiftest_util_set_msys(self) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody_system object + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody_system object end subroutine swiftest_util_set_msys module subroutine swiftest_util_set_mu_pl(self, cb) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_set_mu_pl module subroutine swiftest_util_set_mu_tp(self, cb) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_set_mu_tp module subroutine swiftest_util_set_particle_info(self, name, particle_type, status, origin_type, origin_time, collision_id, & origin_rh, origin_vh, discard_time, discard_rh, discard_vh, discard_body_id) implicit none class(swiftest_particle_info), intent(inout) :: self - character(len=*), intent(in), optional :: name !! Non-unique name - character(len=*), intent(in), optional :: particle_type !! String containing a description of the particle type (e.g. Central Body, Massive Body, Test Particle) - character(len=*), intent(in), optional :: status !! Particle status description: Active, Merged, Fragmented, etc. - character(len=*), intent(in), optional :: origin_type !! String containing a description of the origin of the particle (e.g. Initial Conditions, Supercatastrophic, Disruption, etc.) - real(DP), intent(in), optional :: origin_time !! The time of the particle's formation - integer(I4B), intent(in), optional :: collision_id !! The ID fo the collision that formed the particle - real(DP), dimension(:), intent(in), optional :: origin_rh !! The heliocentric distance vector at the time of the particle's formation - real(DP), dimension(:), intent(in), optional :: origin_vh !! The heliocentric velocity vector at the time of the particle's formation - real(DP), intent(in), optional :: discard_time !! The time of the particle's discard - real(DP), dimension(:), intent(in), optional :: discard_rh !! The heliocentric distance vector at the time of the particle's discard - real(DP), dimension(:), intent(in), optional :: discard_vh !! The heliocentric velocity vector at the time of the particle's discard - integer(I4B), intent(in), optional :: discard_body_id !! The id of the other body involved in the discard (0 if no other body involved) + character(len=*), intent(in), optional :: name + !! Non-unique name + character(len=*), intent(in), optional :: particle_type + !! String containing a description of the particle type (e.g. Central Body, Massive Body, Test Particle) + character(len=*), intent(in), optional :: status + !! Particle status description: Active, Merged, Fragmented, etc. + character(len=*), intent(in), optional :: origin_type + !! String containing a description of the origin of the particle (e.g. Initial Conditions, Disruption, etc.) + real(DP), intent(in), optional :: origin_time + !! The time of the particle's formation + integer(I4B), intent(in), optional :: collision_id + !! The ID fo the collision that formed the particle + real(DP), dimension(:), intent(in), optional :: origin_rh + !! The heliocentric distance vector at the time of the particle's formation + real(DP), dimension(:), intent(in), optional :: origin_vh + !! The heliocentric velocity vector at the time of the particle's formation + real(DP), intent(in), optional :: discard_time + !! The time of the particle's discard + real(DP), dimension(:), intent(in), optional :: discard_rh + !! The heliocentric distance vector at the time of the particle's discard + real(DP), dimension(:), intent(in), optional :: discard_vh + !! The heliocentric velocity vector at the time of the particle's discard + integer(I4B), intent(in), optional :: discard_body_id + !! The id of the other body involved in the discard (0 if no other body involved) end subroutine swiftest_util_set_particle_info module subroutine swiftest_util_set_rhill(self,cb) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_set_rhill module subroutine swiftest_util_set_renc_I4B(self, scale) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - integer(I4B), intent(in) :: scale !! Input scale factor (multiplier of Hill's sphere size) + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + integer(I4B), intent(in) :: scale + !! Input scale factor (multiplier of Hill's sphere size) end subroutine swiftest_util_set_renc_I4B module subroutine swiftest_util_set_renc_DP(self, scale) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - real(DP), intent(in) :: scale !! Input scale factor (multiplier of Hill's sphere size) + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + real(DP), intent(in) :: scale + !! Input scale factor (multiplier of Hill's sphere size) end subroutine swiftest_util_set_renc_DP module subroutine swiftest_util_set_rhill_approximate(self,cb) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_cb), intent(inout) :: cb + !! Swiftest central body object end subroutine swiftest_util_set_rhill_approximate module subroutine swiftest_util_snapshot_save(storage, snapshot) use base, only : base_storage implicit none - class(base_storage), allocatable, intent(inout) :: storage !! Storage ncounter storage object - class(*), intent(in) :: snapshot !! Object to snapshot + class(base_storage), allocatable, intent(inout) :: storage + !! Storage ncounter storage object + class(*), intent(in) :: snapshot + !! Object to snapshot end subroutine swiftest_util_snapshot_save module subroutine swiftest_util_snapshot_system(self, param, nbody_system, t, arg) implicit none - class(swiftest_storage), intent(inout) :: self !! Swiftest storage object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object to store - real(DP), intent(in), optional :: t !! Time of snapshot if different from nbody_system time - character(*), intent(in), optional :: arg !! Optional argument (needed for extended storage type used in collision snapshots) + class(swiftest_storage), intent(inout) :: self + !! Swiftest storage object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system object to store + real(DP), intent(in), optional :: t + !! Time of snapshot if different from nbody_system time + character(*), intent(in), optional :: arg + !! Optional argument (needed for extended storage type used in collision snapshots) end subroutine swiftest_util_snapshot_system end interface @@ -1664,16 +2407,22 @@ end subroutine swiftest_util_snapshot_system interface util_sort_rearrange module subroutine swiftest_util_sort_rearrange_arr_info(arr, ind, n) implicit none - type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I4B), intent(in) :: n !! Number of elements in arr and ind to rearrange + type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I4B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I4B), intent(in) :: n + !! Number of elements in arr and ind to rearrange end subroutine swiftest_util_sort_rearrange_arr_info pure module subroutine swiftest_util_sort_rearrange_arr_kin(arr, ind, n) implicit none - type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), intent(in) :: ind !! Index to rearrange against - integer(I4B), intent(in) :: n !! Number of elements in arr and ind to rearrange + type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: arr + !! Destination array + integer(I4B), dimension(:), intent(in) :: ind + !! Index to rearrange against + integer(I4B), intent(in) :: n + !! Number of elements in arr and ind to rearrange end subroutine swiftest_util_sort_rearrange_arr_kin end interface util_sort_rearrange @@ -1681,41 +2430,56 @@ end subroutine swiftest_util_sort_rearrange_arr_kin interface module subroutine swiftest_util_sort_rearrange_body(self, ind) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - integer(I4B), dimension(:), intent(in) :: ind !! Index array used to restructure the body (should contain all 1:n index values in the desired order) + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + integer(I4B), dimension(:), intent(in) :: ind + !! Index array used to restructure the body (should contain all 1:n index values in the desired order) end subroutine swiftest_util_sort_rearrange_body module subroutine swiftest_util_sort_rearrange_pl(self, ind) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - integer(I4B), dimension(:), intent(in) :: ind !! Index array used to restructure the body (should contain all 1:n index values in the desired order) + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + integer(I4B), dimension(:), intent(in) :: ind + !! Index array used to restructure the body (should contain all 1:n index values in the desired order) end subroutine swiftest_util_sort_rearrange_pl module subroutine swiftest_util_sort_rearrange_tp(self, ind) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - integer(I4B), dimension(:), intent(in) :: ind !! Index array used to restructure the body (should contain all 1:n index values in the desired order) + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + integer(I4B), dimension(:), intent(in) :: ind + !! Index array used to restructure the body (should contain all 1:n index values in the desired order) end subroutine swiftest_util_sort_rearrange_tp module subroutine swiftest_util_sort_body(self, sortby, ascending) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - character(*), intent(in) :: sortby !! Sorting attribute - logical, intent(in) :: ascending !! Logical flag indicating whether or not the sorting should be in ascending or descending order + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + character(*), intent(in) :: sortby + !! Sorting attribute + logical, intent(in) :: ascending + !! Logical flag indicating whether or not the sorting should be in ascending or descending order end subroutine swiftest_util_sort_body module subroutine swiftest_util_sort_pl(self, sortby, ascending) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest body object - character(*), intent(in) :: sortby !! Sorting attribute - logical, intent(in) :: ascending !! Logical flag indicating whether or not the sorting should be in ascending or descending order + class(swiftest_pl), intent(inout) :: self + !! Swiftest body object + character(*), intent(in) :: sortby + !! Sorting attribute + logical, intent(in) :: ascending + !! Logical flag indicating whether or not the sorting should be in ascending or descending order end subroutine swiftest_util_sort_pl module subroutine swiftest_util_sort_tp(self, sortby, ascending) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest body object - character(*), intent(in) :: sortby !! Sorting attribute - logical, intent(in) :: ascending !! Logical flag indicating whether or not the sorting should be in ascending or descending order + class(swiftest_tp), intent(inout) :: self + !! Swiftest body object + character(*), intent(in) :: sortby + !! Sorting attribute + logical, intent(in) :: ascending + !! Logical flag indicating whether or not the sorting should be in ascending or descending order end subroutine swiftest_util_sort_tp end interface @@ -1723,44 +2487,64 @@ end subroutine swiftest_util_sort_tp interface util_spill module subroutine swiftest_util_spill_arr_info(keeps, discards, lspill_list, ldestructive) implicit none - type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: discards !! Array of discards - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discardss - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + type(swiftest_particle_info), dimension(:), allocatable, intent(inout) :: discards + !! Array of discards + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discardss + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine swiftest_util_spill_arr_info module subroutine swiftest_util_spill_arr_kin(keeps, discards, lspill_list, ldestructive) implicit none - type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: discards !! Array of discards - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discardss - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: keeps + !! Array of values to keep + type(swiftest_kinship), dimension(:), allocatable, intent(inout) :: discards + !! Array of discards + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discardss + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine swiftest_util_spill_arr_kin end interface interface module subroutine swiftest_util_spill_body(self, discards, lspill_list, ldestructive) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(inout) :: discards !! Discarded object - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + class(swiftest_body), intent(inout) :: self + !! Swiftest body object + class(swiftest_body), intent(inout) :: discards + !! Discarded object + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine swiftest_util_spill_body module subroutine swiftest_util_spill_pl(self, discards, lspill_list, ldestructive) implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_body), intent(inout) :: discards !! Discarded object - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + class(swiftest_pl), intent(inout) :: self + !! Swiftest massive body object + class(swiftest_body), intent(inout) :: discards + !! Discarded object + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine swiftest_util_spill_pl module subroutine swiftest_util_spill_tp(self, discards, lspill_list, ldestructive) implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_body), intent(inout) :: discards !! Discarded object - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + class(swiftest_tp), intent(inout) :: self + !! Swiftest test particle object + class(swiftest_body), intent(inout) :: discards + !! Discarded object + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine swiftest_util_spill_tp end interface @@ -1768,8 +2552,10 @@ end subroutine swiftest_util_spill_tp interface module subroutine swiftest_util_valid_id_system(self, param) implicit none - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: self + !! Swiftest nbody system object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_util_valid_id_system module subroutine swiftest_util_version() @@ -1782,24 +2568,30 @@ end subroutine swiftest_util_version module subroutine swiftest_coarray_balance_system(nbody_system, param) !! author: David A. Minton !! - !! Checks whether or not the system needs to be rebalance. Rebalancing occurs when the image with the smallest number of test particles - !! has <90% of that of the image with the largest number of test particles. + !! Checks whether or not the system needs to be rebalance. Rebalancing occurs when the image with the smallest number of + !! test particles has <90% of that of the image with the largest number of test particles. implicit none ! Arguments - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_coarray_balance_system module subroutine swiftest_coarray_collect_system(nbody_system, param) implicit none - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_coarray_collect_system module subroutine swiftest_coarray_distribute_system(nbody_system, param) implicit none - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(swiftest_nbody_system), intent(inout) :: nbody_system + !! Swiftest nbody system + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters end subroutine swiftest_coarray_distribute_system end interface @@ -1834,87 +2626,73 @@ module subroutine swiftest_coarray_component_collect_info_arr1D(var,dest_img) interface module subroutine swiftest_coarray_coclone_body(self) implicit none - class(swiftest_body),intent(inout),codimension[*] :: self !! Swiftest body object + class(swiftest_body),intent(inout),codimension[*] :: self + !! Swiftest body object end subroutine swiftest_coarray_coclone_body module subroutine swiftest_coarray_coclone_cb(self) implicit none - class(swiftest_cb),intent(inout),codimension[*] :: self !! Swiftest cb object + class(swiftest_cb),intent(inout),codimension[*] :: self + !! Swiftest cb object end subroutine swiftest_coarray_coclone_cb module subroutine swiftest_coarray_coclone_kin(self) implicit none - class(swiftest_kinship),intent(inout),codimension[*] :: self !! Swiftest kinship object + class(swiftest_kinship),intent(inout),codimension[*] :: self + !! Swiftest kinship object end subroutine swiftest_coarray_coclone_kin module subroutine swiftest_coarray_coclone_nc(self) implicit none - class(swiftest_netcdf_parameters),intent(inout),codimension[*] :: self !! Swiftest body object + class(swiftest_netcdf_parameters),intent(inout),codimension[*] :: self + !! Swiftest body object end subroutine swiftest_coarray_coclone_nc module subroutine swiftest_coarray_coclone_pl(self) implicit none - class(swiftest_pl),intent(inout),codimension[*] :: self !! Swiftest pl object + class(swiftest_pl),intent(inout),codimension[*] :: self + !! Swiftest pl object end subroutine swiftest_coarray_coclone_pl module subroutine swiftest_coarray_coclone_tp(self) implicit none - class(swiftest_tp),intent(inout),codimension[*] :: self !! Swiftest tp object + class(swiftest_tp),intent(inout),codimension[*] :: self + !! Swiftest tp object end subroutine swiftest_coarray_coclone_tp module subroutine swiftest_coarray_coclone_system(self) implicit none - class(swiftest_nbody_system),intent(inout),codimension[*] :: self !! Swiftest nbody system object + class(swiftest_nbody_system),intent(inout),codimension[*] :: self + !! Swiftest nbody system object end subroutine swiftest_coarray_coclone_system module subroutine swiftest_coarray_cocollect_body(self) implicit none - class(swiftest_body),intent(inout), codimension[*] :: self !! Swiftest body object + class(swiftest_body),intent(inout), codimension[*] :: self + !! Swiftest body object end subroutine swiftest_coarray_cocollect_body module subroutine swiftest_coarray_cocollect_tp(self) implicit none - class(swiftest_tp),intent(inout), codimension[*] :: self !! Swiftest tp object + class(swiftest_tp),intent(inout), codimension[*] :: self + !! Swiftest tp object end subroutine swiftest_coarray_cocollect_tp end interface #endif - interface - module subroutine swiftest_sph_g_acc_one(GMcb, r_0, phi_cb, rh, c_lm, g_sph, GMpl, aoblcb) - implicit none - real(DP), intent(in) :: GMcb !! GMass of the central body - real(DP), intent(in) :: r_0 !! radius of the central body - real(DP), intent(in) :: phi_cb !! rotation phase angle of the central body - real(DP), intent(in), dimension(:) :: rh !! distance vector of body - real(DP), intent(in), dimension(:, :, :) :: c_lm !! Spherical Harmonic coefficients - real(DP), intent(out), dimension(NDIM) :: g_sph !! acceleration vector - real(DP), intent(in), optional :: GMpl !! Mass of input body if it is not a test particle - real(DP), dimension(:), intent(inout), optional :: aoblcb!! Barycentric acceleration of central body (only for massive input bodies) - end subroutine swiftest_sph_g_acc_one - - module subroutine swiftest_sph_g_acc_pl_all(self, nbody_system) - implicit none - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - end subroutine swiftest_sph_g_acc_pl_all - - module subroutine swiftest_sph_g_acc_tp_all(self, nbody_system) - implicit none - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_nbody_system), intent(inout) :: nbody_system !! Swiftest nbody system object - end subroutine swiftest_sph_g_acc_tp_all - - end interface - contains subroutine swiftest_final_kin(self) - !! author: David A. Minton - !! - !! Finalize the swiftest kinship object - deallocates all allocatables + + !! author: David A. Minton + + !! + + !! Finalize the swiftest kinship object - deallocates all allocatables implicit none ! Argument - type(swiftest_kinship), intent(inout) :: self !! SyMBA kinship object + type(swiftest_kinship), intent(inout) :: self + !! SyMBA kinship object call self%dealloc() @@ -1923,9 +2701,12 @@ end subroutine swiftest_final_kin subroutine swiftest_final_storage(self) - !! author: David A. Minton - !! - !! Finalizer for the storage data type + + !! author: David A. Minton + + !! + + !! Finalizer for the storage data type implicit none ! Arguments type(swiftest_storage) :: self diff --git a/src/swiftest/swiftest_obl.f90 b/src/swiftest/swiftest_obl.f90 index 8b07f7b2f..42c03eb91 100644 --- a/src/swiftest/swiftest_obl.f90 +++ b/src/swiftest/swiftest_obl.f90 @@ -9,15 +9,15 @@ submodule (swiftest) s_swiftest_obl use swiftest - use operators + use shgrav contains pure function matinv3(A) result(B) - !! Performs a direct calculation of the inverse of a 3×3 matrix. - !! - !! from https://fortranwiki.org/fortran/show/Matrix+inversion - !! + !! Performs a direct calculation of the inverse of a 3×3 matrix. + !! + !! from https://fortranwiki.org/fortran/show/Matrix+inversion + !! real(DP), intent(in) :: A(3,3) !! Matrix real(DP) :: B(3,3) !! Inverse matrix @@ -44,7 +44,8 @@ pure function matinv3(A) result(B) module subroutine swiftest_obl_rot_matrix(n, rot, rot_matrix, rot_matrix_inv) !! author: Kaustub P. Anand !! - !! Generate a rotation matrix and its inverse to rotate the coordinate frame to align the rotation axis along the z axis for correct spin calculation + !! Generate a rotation matrix and its inverse to rotate the coordinate frame to align the rotation axis along the z axis for + !! correct spin calculation !! implicit none @@ -95,7 +96,8 @@ module subroutine swiftest_obl_rot_matrix(n, rot, rot_matrix, rot_matrix_inv) continue end if - rot_matrix_inv(i, j) = rot_matrix_inv(i, j) + u(i) * u(j) * (1 - cos(theta)) + S_matrix(i, j) * sin(theta) ! Skew-symmetric matrix + Tensor product matrix + ! Skew-symmetric matrix + Tensor product matrix + rot_matrix_inv(i, j) = rot_matrix_inv(i, j) + u(i) * u(j) * (1 - cos(theta)) + S_matrix(i, j) * sin(theta) end do end do @@ -136,7 +138,8 @@ module subroutine swiftest_obl_acc(n, GMcb, j2rp2, j4rp4, rh, lmask, aobl, rot, real(DP), dimension(:,:), intent(out) :: aobl !! Barycentric acceleration of bodies due to central body oblateness real(DP), dimension(NDIM), intent(in) :: rot !! Central body rotation matrix real(DP), dimension(:), intent(in), optional :: GMpl !! Masses of input bodies if they are not test particles - real(DP), dimension(:), intent(out), optional :: aoblcb !! Barycentric acceleration of central body (only needed if input bodies are massive) + real(DP), dimension(:), intent(out), optional :: aoblcb + !! Barycentric acceleration of central body (only needed if input bodies are massive) ! Internals integer(I4B) :: i @@ -209,7 +212,7 @@ module subroutine swiftest_obl_acc(n, GMcb, j2rp2, j4rp4, rh, lmask, aobl, rot, end subroutine swiftest_obl_acc - module subroutine swiftest_obl_acc_pl(self, nbody_system) + module subroutine swiftest_non_spherical_cb_acc_pl(self, nbody_system) !! author: David A. Minton !! !! Compute the barycentric accelerations of massive bodies due to the oblateness of the central body @@ -227,7 +230,11 @@ module subroutine swiftest_obl_acc_pl(self, nbody_system) associate(pl => self, cb => nbody_system%cb) npl = self%nbody - call swiftest_obl_acc(npl, cb%Gmass, cb%j2rp2, cb%j4rp4, pl%rh, pl%lmask, pl%aobl, cb%rot, pl%Gmass, cb%aobl) + if (allocated(cb%c_lm)) then + call shgrav_acc(self, nbody_system) + else + call swiftest_obl_acc(npl, cb%Gmass, cb%j2rp2, cb%j4rp4, pl%rh, pl%lmask, pl%aobl, cb%rot, pl%Gmass, cb%aobl) + end if #ifdef DOCONLOC do concurrent(i = 1:npl, pl%lmask(i)) shared(cb,pl) @@ -239,11 +246,10 @@ module subroutine swiftest_obl_acc_pl(self, nbody_system) end associate return - - end subroutine swiftest_obl_acc_pl + end subroutine swiftest_non_spherical_cb_acc_pl - module subroutine swiftest_obl_acc_tp(self, nbody_system) + module subroutine swiftest_non_spherical_cb_acc_tp(self, nbody_system) !! author: David A. Minton !! !! Compute the barycentric accelerations of massive bodies due to the oblateness of the central body @@ -262,7 +268,11 @@ module subroutine swiftest_obl_acc_tp(self, nbody_system) associate(tp => self, cb => nbody_system%cb) ntp = self%nbody - call swiftest_obl_acc(ntp, cb%Gmass, cb%j2rp2, cb%j4rp4, tp%rh, tp%lmask, tp%aobl, cb%rot) + if (allocated(cb%c_lm)) then + call shgrav_acc(self, nbody_system) + else + call swiftest_obl_acc(ntp, cb%Gmass, cb%j2rp2, cb%j4rp4, tp%rh, tp%lmask, tp%aobl, cb%rot) + end if if (nbody_system%lbeg) then aoblcb = cb%aoblbeg else @@ -278,9 +288,9 @@ module subroutine swiftest_obl_acc_tp(self, nbody_system) end do end associate - return - end subroutine swiftest_obl_acc_tp + return + end subroutine swiftest_non_spherical_cb_acc_tp module subroutine swiftest_obl_pot_system(self) @@ -302,6 +312,7 @@ module subroutine swiftest_obl_pot_system(self) associate(nbody_system => self, pl => self%pl, cb => self%cb) npl = self%pl%nbody + if (npl == 0) return if (.not. any(pl%lmask(1:npl))) return #ifdef DOCONLOC do concurrent (i = 1:npl, pl%lmask(i)) shared(cb,pl,oblpot_arr) @@ -320,7 +331,8 @@ end subroutine swiftest_obl_pot_system elemental function swiftest_obl_pot_one(GMcb, GMpl, j2rp2, j4rp4, zh, irh) result(oblpot) !! author: David A. Minton !! - !! Compute the contribution to the total gravitational potential due solely to the oblateness of the central body from a single massive body + !! Compute the contribution to the total gravitational potential due solely to the oblateness of the central body from a + !! single massive body !! Returned value does not include monopole term or terms higher than J4 !! !! Reference: MacMillan, W. D. 1958. The Theory of the Potential, (Dover Publications), 363. diff --git a/src/swiftest/swiftest_util.f90 b/src/swiftest/swiftest_util.f90 index bcc4a5398..e1bfbb17b 100644 --- a/src/swiftest/swiftest_util.f90 +++ b/src/swiftest/swiftest_util.f90 @@ -1213,32 +1213,36 @@ module subroutine swiftest_util_get_energy_and_momentum_system(self, param) nbody_system%ke_orbit = 0.0_DP nbody_system%ke_spin = 0.0_DP - kepl(:) = 0.0_DP - Lplorbit(:,:) = 0.0_DP - Lplspin(:,:) = 0.0_DP - - pl%lmask(1:npl) = pl%status(1:npl) /= INACTIVE - - nbody_system%GMtot = cb%Gmass + sum(pl%Gmass(1:npl), pl%lmask(1:npl)) + nbody_system%GMtot = cb%Gmass + if (npl > 0) then + kepl(:) = 0.0_DP + Lplorbit(:,:) = 0.0_DP + Lplspin(:,:) = 0.0_DP + pl%lmask(1:npl) = pl%status(1:npl) /= INACTIVE + nbody_system%GMtot = nbody_system%GMtot + sum(pl%Gmass(1:npl), pl%lmask(1:npl)) + end if + kecb = cb%mass * dot_product(cb%vb(:), cb%vb(:)) nbody_system%be_cb = -3*cb%Gmass * cb%mass / (5 * cb%radius) Lcborbit(:) = cb%mass * (cb%rb(:) .cross. cb%vb(:)) + if (npl > 0) then #ifdef DOCONLOC - do concurrent (i = 1:npl, pl%lmask(i)) shared(pl,Lplorbit,kepl,npl) local(h) + do concurrent (i = 1:npl, pl%lmask(i)) shared(pl,Lplorbit,kepl,npl) local(h) #else - do concurrent (i = 1:npl, pl%lmask(i)) + do concurrent (i = 1:npl, pl%lmask(i)) #endif - h(1) = pl%rb(2,i) * pl%vb(3,i) - pl%rb(3,i) * pl%vb(2,i) - h(2) = pl%rb(3,i) * pl%vb(1,i) - pl%rb(1,i) * pl%vb(3,i) - h(3) = pl%rb(1,i) * pl%vb(2,i) - pl%rb(2,i) * pl%vb(1,i) - + h(1) = pl%rb(2,i) * pl%vb(3,i) - pl%rb(3,i) * pl%vb(2,i) + h(2) = pl%rb(3,i) * pl%vb(1,i) - pl%rb(1,i) * pl%vb(3,i) + h(3) = pl%rb(1,i) * pl%vb(2,i) - pl%rb(2,i) * pl%vb(1,i) + ! Angular momentum from orbit - Lplorbit(:,i) = pl%mass(i) * h(:) + Lplorbit(:,i) = pl%mass(i) * h(:) - ! Kinetic energy from orbit - kepl(i) = pl%mass(i) * dot_product(pl%vb(:,i), pl%vb(:,i)) - end do + ! Kinetic energy from orbit + kepl(i) = pl%mass(i) * dot_product(pl%vb(:,i), pl%vb(:,i)) + end do + end if if (param%lrotation) then kespincb = cb%mass * cb%Ip(3) * cb%radius**2 * dot_product(cb%rot(:), cb%rot(:)) @@ -1246,56 +1250,71 @@ module subroutine swiftest_util_get_energy_and_momentum_system(self, param) ! For simplicity, we always assume that the rotation pole is the 3rd principal axis Lcbspin(:) = cb%Ip(3) * cb%mass * cb%radius**2 * cb%rot(:) + if (npl > 0) then #ifdef DOCONLOC - do concurrent (i = 1:npl, pl%lmask(i)) shared(pl,Lplspin,kespinpl) + do concurrent (i = 1:npl, pl%lmask(i)) shared(pl,Lplspin,kespinpl) #else - do concurrent (i = 1:npl, pl%lmask(i)) + do concurrent (i = 1:npl, pl%lmask(i)) #endif - ! Currently we assume that the rotation pole is the 3rd principal axis - ! Angular momentum from spin - Lplspin(:,i) = pl%mass(i) * pl%Ip(3,i) * pl%radius(i)**2 * pl%rot(:,i) + ! Currently we assume that the rotation pole is the 3rd principal axis + ! Angular momentum from spin + Lplspin(:,i) = pl%mass(i) * pl%Ip(3,i) * pl%radius(i)**2 * pl%rot(:,i) - ! Kinetic energy from spin - kespinpl(i) = pl%mass(i) * pl%Ip(3,i) * pl%radius(i)**2 * dot_product(pl%rot(:,i), pl%rot(:,i)) - end do + ! Kinetic energy from spin + kespinpl(i) = pl%mass(i) * pl%Ip(3,i) * pl%radius(i)**2 * dot_product(pl%rot(:,i), pl%rot(:,i)) + end do - nbody_system%ke_spin = 0.5_DP * (kespincb + sum(kespinpl(1:npl), pl%lmask(1:npl))) + nbody_system%ke_spin = 0.5_DP * (kespincb + sum(kespinpl(1:npl), pl%lmask(1:npl))) + else + nbody_system%ke_spin = 0.5_DP * kespincb + end if + if (npl > 0) then #ifdef DOCONLOC - do concurrent (j = 1:NDIM) shared(nbody_system,pl,Lplspin,Lcbspin) + do concurrent (j = 1:NDIM) shared(nbody_system,pl,Lplspin,Lcbspin) #else - do concurrent (j = 1:NDIM) + do concurrent (j = 1:NDIM) #endif - nbody_system%L_spin(j) = Lcbspin(j) + sum(Lplspin(j,1:npl), pl%lmask(1:npl)) - end do + nbody_system%L_spin(j) = Lcbspin(j) + sum(Lplspin(j,1:npl), pl%lmask(1:npl)) + end do + else + nbody_system%L_spin(:) = Lcbspin(:) + end if else nbody_system%ke_spin = 0.0_DP nbody_system%L_spin(:) = 0.0_DP end if - - if (param%lflatten_interactions) then - call swiftest_util_get_potential_energy(npl, pl%nplpl, pl%k_plpl, pl%lmask, cb%Gmass, pl%Gmass, pl%mass, pl%rb, & - nbody_system%pe) - else - call swiftest_util_get_potential_energy(npl, pl%lmask, cb%Gmass, pl%Gmass, pl%mass, pl%rb, nbody_system%pe) + + if (npl > 0) then + if (param%lflatten_interactions) then + call swiftest_util_get_potential_energy(npl, pl%nplpl, pl%k_plpl, pl%lmask, cb%Gmass, pl%Gmass, pl%mass, pl%rb, & + nbody_system%pe) + else + call swiftest_util_get_potential_energy(npl, pl%lmask, cb%Gmass, pl%Gmass, pl%mass, pl%rb, nbody_system%pe) + end if end if ! Potential energy from the oblateness term - if (param%loblatecb) then + if (param%lnon_spherical_cb) then call nbody_system%obl_pot() nbody_system%pe = nbody_system%pe + nbody_system%oblpot end if - nbody_system%ke_orbit = 0.5_DP * (kecb + sum(kepl(1:npl), pl%lmask(1:npl))) + if (npl > 0) then + nbody_system%ke_orbit = 0.5_DP * (kecb + sum(kepl(1:npl), pl%lmask(1:npl))) #ifdef DOCONLOC - do concurrent (j = 1:NDIM) shared(nbody_system,pl,Lcborbit,Lplorbit,npl) + do concurrent (j = 1:NDIM) shared(nbody_system,pl,Lcborbit,Lplorbit,npl) #else - do concurrent (j = 1:NDIM) + do concurrent (j = 1:NDIM) #endif - nbody_system%L_orbit(j) = Lcborbit(j) + sum(Lplorbit(j,1:npl), pl%lmask(1:npl)) - end do + nbody_system%L_orbit(j) = Lcborbit(j) + sum(Lplorbit(j,1:npl), pl%lmask(1:npl)) + end do + else + nbody_system%ke_orbit = 0.5_DP * kecb + nbody_system%L_orbit(:) = Lcborbit(:) + end if - if ((param%lclose)) then + if ((param%lclose .and. (npl > 0))) then nbody_system%be = sum(-3*pl%Gmass(1:npl)*pl%mass(1:npl)/(5*pl%radius(1:npl)), pl%lmask(1:npl)) else nbody_system%be = 0.0_DP @@ -2706,7 +2725,7 @@ module subroutine swiftest_util_setup_body(self, n, param) self%peri(:) = 0.0_DP self%atp(:) = 0.0_DP - if (param%loblatecb .or. param%lshgrav) then + if (param%lnon_spherical_cb) then allocate(self%aobl(NDIM, n)) self%aobl(:,:) = 0.0_DP end if diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 7c95da30a..2d22ef299 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -48,11 +48,13 @@ subroutine symba_discard_cb_pl(pl, nbody_system, param) write(message, *) trim(adjustl(pl%info(i)%name)) // " (" // trim(adjustl(idstr)) // ")" // & " too far from the central body at t = " // trim(adjustl(timestr)) call swiftest_io_log_one_message(COLLISION_LOG_OUT, "") - call swiftest_io_log_one_message(COLLISION_LOG_OUT, "***********************************************************" // & - "***********************************************************") + call swiftest_io_log_one_message(COLLISION_LOG_OUT, & + "***********************************************************" // & + "***********************************************************") call swiftest_io_log_one_message(COLLISION_LOG_OUT, message) - call swiftest_io_log_one_message(COLLISION_LOG_OUT, "***********************************************************" // & - "***********************************************************") + call swiftest_io_log_one_message(COLLISION_LOG_OUT, & + "***********************************************************" // & + "***********************************************************") call swiftest_io_log_one_message(COLLISION_LOG_OUT, "") call pl%info(i)%set_value(status="DISCARDED_RMAX", discard_time=nbody_system%t, discard_rh=pl%rh(:,i), & discard_vh=pl%vh(:,i)) @@ -65,11 +67,13 @@ subroutine symba_discard_cb_pl(pl, nbody_system, param) write(message, *) trim(adjustl(pl%info(i)%name)) // " (" // trim(adjustl(idstr)) // ")" // & " too close to the central body at t = " // trim(adjustl(timestr)) call swiftest_io_log_one_message(COLLISION_LOG_OUT, "") - call swiftest_io_log_one_message(COLLISION_LOG_OUT, "************************************************************" // & - "************************************************************") + call swiftest_io_log_one_message(COLLISION_LOG_OUT, & + "************************************************************" // & + "************************************************************") call swiftest_io_log_one_message(COLLISION_LOG_OUT, message) - call swiftest_io_log_one_message(COLLISION_LOG_OUT, "************************************************************" // & - "************************************************************") + call swiftest_io_log_one_message(COLLISION_LOG_OUT, & + "************************************************************" // & + "************************************************************") call swiftest_io_log_one_message(COLLISION_LOG_OUT, "") call pl%info(i)%set_value(status="DISCARDED_RMIN", discard_time=nbody_system%t, discard_rh=pl%rh(:,i), & discard_vh=pl%vh(:,i), discard_body_id=cb%id) @@ -86,11 +90,13 @@ subroutine symba_discard_cb_pl(pl, nbody_system, param) write(message, *) trim(adjustl(pl%info(i)%name)) // " (" // trim(adjustl(idstr)) // ")" // & " is unbound and too far from barycenter at t = " // trim(adjustl(timestr)) call swiftest_io_log_one_message(COLLISION_LOG_OUT, "") - call swiftest_io_log_one_message(COLLISION_LOG_OUT, "************************************************************" // & - "************************************************************") + call swiftest_io_log_one_message(COLLISION_LOG_OUT, & + "************************************************************" // & + "************************************************************") call swiftest_io_log_one_message(COLLISION_LOG_OUT, message) - call swiftest_io_log_one_message(COLLISION_LOG_OUT, "************************************************************" // & - "************************************************************") + call swiftest_io_log_one_message(COLLISION_LOG_OUT, & + "************************************************************" // & + "************************************************************") call swiftest_io_log_one_message(COLLISION_LOG_OUT, "") call pl%info(i)%set_value(status="DISCARDED_RMAXU", discard_time=nbody_system%t, discard_rh=pl%rh(:,i), & discard_vh=pl%vh(:,i)) @@ -233,16 +239,6 @@ subroutine symba_discard_nonplpl(pl, nbody_system, param) call symba_discard_cb_pl(pl, nbody_system, param) end if if (param%qmin >= 0.0_DP) call symba_discard_peri_pl(pl, nbody_system, param) - ! if (any(pl%ldiscard(1:npl))) then - ! ldiscard(1:npl) = pl%ldiscard(1:npl) - - ! allocate(plsub, mold=pl) - ! call pl%spill(plsub, ldiscard, ldestructive=.false.) - ! nsub = plsub%nbody - ! nstart = pl_discards%nbody + 1 - ! nend = pl_discards%nbody + nsub - ! call pl_discards%append(plsub, lsource_mask=[(.true., i = 1, nsub)]) - ! end if end associate return @@ -266,7 +262,8 @@ subroutine symba_discard_nonplpl_conservation(pl, nbody_system, param) integer(I4B), dimension(:), allocatable :: discard_index_list associate(npl => pl%nbody) - discard_l_pl(1:npl) = pl%ldiscard(1:npl) .and. .not. pl%lcollision(1:npl) ! These are bodies that are discarded but not flagged as pl-pl collision + discard_l_pl(1:npl) = pl%ldiscard(1:npl) .and. .not. pl%lcollision(1:npl) ! These are bodies that are discarded but not + ! flagged as pl-pl collision ndiscard = count(discard_l_pl(:)) allocate(discard_index_list(ndiscard)) discard_index_list(:) = pack([(i, i = 1, npl)], discard_l_pl(1:npl)) @@ -341,7 +338,8 @@ end subroutine symba_discard_peri_pl module subroutine symba_discard_pl(self, nbody_system, param) !! author: David A. Minton !! - !! Call the various flavors of discards for massive bodies in SyMBA runs, including discards due to colliding with the central body or escaping the nbody_system + !! Call the various flavors of discards for massive bodies in SyMBA runs, including discards due to colliding with the central + !! body or escaping the nbody_system implicit none ! Arguments class(symba_pl), intent(inout) :: self !! SyMBA test particle object diff --git a/src/symba/symba_encounter_check.f90 b/src/symba/symba_encounter_check.f90 index 9dec2072c..768349e7e 100644 --- a/src/symba/symba_encounter_check.f90 +++ b/src/symba/symba_encounter_check.f90 @@ -256,7 +256,7 @@ module function symba_encounter_check_tp(self, param, nbody_system, dt, irec) re integer(I4B), dimension(:), allocatable :: index1, index2 lany_encounter = .false. - if (self%nbody == 0) return + if (self%nbody == 0 .or. nbody_system%pl%nbody == 0) return associate(tp => self, ntp => self%nbody, pl => nbody_system%pl, npl => nbody_system%pl%nbody, cb => nbody_system%cb) call pl%set_renc(irec) diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 38b13978a..46a34a46c 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -19,16 +19,19 @@ module subroutine symba_util_append_pl(self, source, lsource_mask) !! This method will automatically resize the destination body if it is too small implicit none !! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - class(swiftest_body), intent(in) :: source !! Source object to append - logical, dimension(:), intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + class(symba_pl), intent(inout) :: self + !! SyMBA massive body object + class(swiftest_body), intent(in) :: source + !! Source object to append + logical, dimension(:), intent(in) :: lsource_mask + !! Logical mask indicating which elements to append to select type(source) class is (symba_pl) call util_append(self%levelg, source%levelg, lsource_mask=lsource_mask) call util_append(self%levelm, source%levelm, lsource_mask=lsource_mask) - - call swiftest_util_append_pl(self, source, lsource_mask) ! Note: helio_pl does not have its own append method, so we skip back to the base class + ! Note: helio_pl does not have its own append method, so we skip back to the base class + call swiftest_util_append_pl(self, source, lsource_mask) class default write(*,*) "Invalid object passed to the append method. Source must be of class symba_pl or its descendents!" call base_util_exit(FAILURE) @@ -45,16 +48,19 @@ module subroutine symba_util_append_tp(self, source, lsource_mask) !! This method will automatically resize the destination body if it is too small implicit none !! Arguments - class(symba_tp), intent(inout) :: self !! SyMBA test particle object - class(swiftest_body), intent(in) :: source !! Source object to append - logical, dimension(:), intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + class(symba_tp), intent(inout) :: self + !! SyMBA test particle object + class(swiftest_body), intent(in) :: source + !! Source object to append + logical, dimension(:), intent(in) :: lsource_mask + !! Logical mask indicating which elements to append to select type(source) class is (symba_tp) call util_append(self%levelg, source%levelg, lsource_mask=lsource_mask) call util_append(self%levelm, source%levelm, lsource_mask=lsource_mask) - - call swiftest_util_append_tp(self, source, lsource_mask) ! Note: helio_tp does not have its own append method, so we skip back to the base class + ! Note: helio_tp does not have its own append method, so we skip back to the base class + call swiftest_util_append_tp(self, source, lsource_mask) class default write(*,*) "Invalid object passed to the append method. Source must be of class symba_tp or its descendents!" call base_util_exit(FAILURE) @@ -70,7 +76,8 @@ module subroutine symba_util_dealloc_pl(self) !! Deallocates all allocatabale arrays implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object + class(symba_pl), intent(inout) :: self + !! SyMBA massive body object if (allocated(self%levelg)) deallocate(self%levelg) if (allocated(self%levelm)) deallocate(self%levelm) @@ -88,6 +95,7 @@ module subroutine symba_util_dealloc_system(self) implicit none ! Arguments class(symba_nbody_system), intent(inout) :: self + !! SyMBA nbody_system object self%irec = -1 call self%helio_nbody_system%dealloc() @@ -102,7 +110,8 @@ module subroutine symba_util_dealloc_tp(self) !! Deallocates all allocatabale arrays implicit none ! Arguments - class(symba_tp), intent(inout) :: self !! SyMBA test particle object + class(symba_tp), intent(inout) :: self + !! SyMBA test particle object if (allocated(self%levelg)) deallocate(self%levelg) if (allocated(self%levelm)) deallocate(self%levelm) @@ -121,17 +130,20 @@ module subroutine symba_util_fill_pl(self, inserts, lfill_list) !! implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA masive body object - class(swiftest_body), intent(in) :: inserts !! Inserted object - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + class(symba_pl), intent(inout) :: self + !! SyMBA masive body object + class(swiftest_body), intent(in) :: inserts + !! Inserted object + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps associate(keeps => self) select type(inserts) class is (symba_pl) call util_fill(keeps%levelg, inserts%levelg, lfill_list) call util_fill(keeps%levelm, inserts%levelm, lfill_list) - - call swiftest_util_fill_pl(keeps, inserts, lfill_list) ! Note: helio_pl does not have its own fill method, so we skip back to the base class + ! Note: helio_pl does not have its own fill method, so we skip back to the base class + call swiftest_util_fill_pl(keeps, inserts, lfill_list) class default write(*,*) "Invalid object passed to the fill method. Source must be of class symba_pl or its descendents!" call base_util_exit(FAILURE) @@ -150,17 +162,20 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) !! implicit none ! Arguments - class(symba_tp), intent(inout) :: self !! SyMBA test particle object - class(swiftest_body), intent(in) :: inserts !! Inserted object - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + class(symba_tp), intent(inout) :: self + !! SyMBA test particle object + class(swiftest_body), intent(in) :: inserts + !! Inserted object + logical, dimension(:), intent(in) :: lfill_list + !! Logical array of bodies to merge into the keeps associate(keeps => self) select type(inserts) class is (symba_tp) call util_fill(keeps%levelg, inserts%levelg, lfill_list) call util_fill(keeps%levelm, inserts%levelm, lfill_list) - - call swiftest_util_fill_tp(keeps, inserts, lfill_list) ! Note: helio_tp does not have its own fill method, so we skip back to the base class + ! Note: helio_tp does not have its own fill method, so we skip back to the base class + call swiftest_util_fill_tp(keeps, inserts, lfill_list) class default write(*,*) "Invalid object passed to the fill method. Source must be of class symba_tp or its descendents!" call base_util_exit(FAILURE) @@ -184,11 +199,18 @@ module subroutine symba_util_flatten_eucl_plpl(self, param) !! 2019. hal-0204751 implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(symba_pl), intent(inout) :: self + !! SyMBA massive body object + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters ! Internals integer(I8B) :: npl, nplm + if (self%nbody == 0) then + self%nplm = 0 + return + end if + associate(pl => self, nplplm => self%nplplm) npl = int(self%nbody, kind=I8B) if (param%lmtiny_pl) then @@ -198,7 +220,8 @@ module subroutine symba_util_flatten_eucl_plpl(self, param) nplm = npl end if pl%nplm = int(nplm, kind=I4B) - nplplm = nplm * npl - nplm * (nplm + 1_I8B) / 2_I8B ! number of entries in a strict lower triangle, npl x npl, minus first column including only mutually interacting bodies + ! number of entries in a strict lower triangle, npl x npl, minus first column including only mutually interacting bodies + nplplm = nplm * npl - nplm * (nplm + 1_I8B) / 2_I8B call swiftest_util_flatten_eucl_plpl(pl, param) end associate @@ -213,8 +236,10 @@ module subroutine symba_util_resize_pl(self, nnew) !! Checks the current size of a SyMBA massive body object against the requested size and resizes it if it is too small. implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - integer(I4B), intent(in) :: nnew !! New size neded + class(symba_pl), intent(inout) :: self + !! SyMBA massive body object + integer(I4B), intent(in) :: nnew + !! New size neded call util_resize(self%levelg, nnew) call util_resize(self%levelm, nnew) @@ -230,8 +255,10 @@ module subroutine symba_util_resize_tp(self, nnew) !! Checks the current size of a test particle object against the requested size and resizes it if it is too small. implicit none ! Arguments - class(symba_tp), intent(inout) :: self !! SyMBA test particle object - integer(I4B), intent(in) :: nnew !! New size neded + class(symba_tp), intent(inout) :: self + !! SyMBA test particle object + integer(I4B), intent(in):: nnew + !! New size neded call util_resize(self%levelg, nnew) call util_resize(self%levelm, nnew) @@ -248,12 +275,15 @@ module subroutine symba_util_set_renc(self, scale) !! implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - integer(I4B), intent(in) :: scale !! Current recursion depth + class(symba_pl), intent(inout) :: self + !! SyMBA massive body object + integer(I4B), intent(in) :: scale + !! Current recursion depth ! Internals integer(I4B) :: i real(DP) :: rshell_irec + if (self%nbody == 0) return associate(pl => self, npl => self%nbody) rshell_irec = 1._DP do i = 1, scale @@ -274,9 +304,12 @@ module subroutine symba_util_setup_initialize_system(self, system_history, param !! implicit none ! Arguments - class(symba_nbody_system), intent(inout) :: self !! SyMBA nbody_system object - class(swiftest_storage), allocatable, intent(inout) :: system_history !! Stores the system history between output dumps - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + class(symba_nbody_system), intent(inout) :: self + !! SyMBA nbody_system object + class(swiftest_storage),allocatable, intent(inout) :: system_history + !! Stores the system history between output dumps + class(swiftest_parameters), intent(inout) :: param + !! Current run configuration parameters ! Call parent method associate(nbody_system => self) @@ -311,11 +344,14 @@ module subroutine symba_util_setup_pl(self, n, param) !! Equivalent in functionality to David E. Kaufmann's Swifter routine symba_util_setup.f90 implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - integer(I4B), intent(in) :: n !! Number of particles to allocate space for - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameter - - !> Call allocation method for parent class. + class(symba_pl), intent(inout) :: self + !! SyMBA massive body object + integer(I4B), intent(in) :: n + !! Number of particles to allocate space for + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameter + + ! Call allocation method for parent class. call self%helio_pl%setup(n, param) if (n == 0) return @@ -336,9 +372,12 @@ module subroutine symba_util_setup_tp(self, n, param) !! Equivalent in functionality to David E. Kaufmann's Swifter routine whm_util_setup.f90 implicit none ! Arguments - class(symba_tp), intent(inout) :: self !! SyMBA test particle object - integer(I4B), intent(in) :: n !! Number of particles to allocate space for - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameter + class(symba_tp), intent(inout) :: self + !! SyMBA test particle object + integer(I4B), intent(in) :: n + !! Number of particles to allocate space for + class(swiftest_parameters), intent(in) :: param + !! Current run configuration parameter !> Call allocation method for parent class. call self%helio_tp%setup(n, param) @@ -361,9 +400,12 @@ module subroutine symba_util_sort_pl(self, sortby, ascending) !! sortby is a string indicating which array component to sort. implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - character(*), intent(in) :: sortby !! Sorting attribute - logical, intent(in) :: ascending !! Logical flag indicating whether or not the sorting should be in ascending or descending order + class(symba_pl), intent(inout) :: self + !! SyMBA massive body object + character(*), intent(in) :: sortby + !! Sorting attribute + logical, intent(in) :: ascending + !! Logical flag indicating whether or not the sorting should be in ascending or descending order ! Internals integer(I4B), dimension(:), allocatable :: ind integer(I4B) :: direction @@ -402,9 +444,12 @@ module subroutine symba_util_sort_tp(self, sortby, ascending) !! sortby is a string indicating which array component to sort. implicit none ! Arguments - class(symba_tp), intent(inout) :: self !! SyMBA test particle object - character(*), intent(in) :: sortby !! Sorting attribute - logical, intent(in) :: ascending !! Logical flag indicating whether or not the sorting should be in ascending or descending order + class(symba_tp), intent(inout) :: self + !! SyMBA test particle object + character(*), intent(in) :: sortby + !! Sorting attribute + logical, intent(in) :: ascending + !! Logical flag indicating whether or not the sorting should be in ascending or descending order ! Internals integer(I4B), dimension(:), allocatable :: ind integer(I4B) :: direction @@ -444,8 +489,10 @@ module subroutine symba_util_sort_rearrange_pl(self, ind) !! This is a helper utility used to make polymorphic sorting work on Swiftest structures. implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - integer(I4B), dimension(:), intent(in) :: ind !! Index array used to restructure the body (should contain all 1:n index values in the desired order) + class(symba_pl), intent(inout) :: self ! + ! SyMBA massive body object + integer(I4B), dimension(:), intent(in) :: ind + !! Index array used to restructure the body (should contain all 1:n index values in the desired order) associate(pl => self, npl => self%nbody) call util_sort_rearrange(pl%levelg, ind, npl) @@ -464,8 +511,10 @@ module subroutine symba_util_sort_rearrange_tp(self, ind) !! This is a helper utility used to make polymorphic sorting work on Swiftest structures. implicit none ! Arguments - class(symba_tp), intent(inout) :: self !! SyMBA test particle object - integer(I4B), dimension(:), intent(in) :: ind !! Index array used to restructure the body (should contain all 1:n index values in the desired order) + class(symba_tp), intent(inout) :: self + !! SyMBA test particle object + integer(I4B), dimension(:), intent(in) :: ind + !! Index array used to restructure the body (should contain all 1:n index values in the desired order) associate(tp => self, ntp => self%nbody) call util_sort_rearrange(tp%nplenc, ind, ntp) @@ -486,10 +535,14 @@ module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - class(swiftest_body), intent(inout) :: discards !! Discarded object - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter body by removing the discard list + class(symba_pl), intent(inout) :: self + !! SyMBA massive body object + class(swiftest_body), intent(inout) :: discards + !! Discarded object + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter body by removing the discard list ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps !> Spill all the common components @@ -517,10 +570,14 @@ module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 implicit none ! Arguments - class(symba_tp), intent(inout) :: self !! SyMBA test particle object - class(swiftest_body), intent(inout) :: discards !! Discarded object - logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards - logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter body by removing the discard list + class(symba_tp), intent(inout) :: self + !! SyMBA test particle object + class(swiftest_body), intent(inout) :: discards + !! Discarded object + logical, dimension(:), intent(in) :: lspill_list + !! Logical array of bodies to spill into the discards + logical, intent(in) :: ldestructive + !! Logical flag indicating whether or not this operation should alter body by removing the discard list ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps !> Spill all the common components diff --git a/src/whm/whm_kick.f90 b/src/whm/whm_kick.f90 index e0bb2e70f..0f58e9d5e 100644 --- a/src/whm/whm_kick.f90 +++ b/src/whm/whm_kick.f90 @@ -43,8 +43,8 @@ module subroutine whm_kick_getacch_pl(self, nbody_system, param, t, lbeg) call whm_kick_getacch_ah2(cb, pl) call pl%accel_int(param) - if (param%loblatecb) then - call pl%accel_obl(nbody_system) + if (param%lnon_spherical_cb) then + call pl%accel_non_spherical_cb(nbody_system) if (lbeg) then cb%aoblbeg = cb%aobl else @@ -58,12 +58,7 @@ module subroutine whm_kick_getacch_pl(self, nbody_system, param, t, lbeg) ! end if end if - if(param%lshgrav) then - call pl%accel_sph(nbody_system) - end if - if (param%lgr) call pl%accel_gr(param) - if (param%lextra_force) call pl%accel_user(nbody_system, param, t, lbeg) end associate @@ -119,8 +114,7 @@ module subroutine whm_kick_getacch_tp(self, nbody_system, param, t, lbeg) end if end if - if (param%loblatecb) call tp%accel_obl(nbody_system) - if (param%lshgrav) call tp%accel_sph(nbody_system) + if (param%lnon_spherical_cb) call tp%accel_non_spherical_cb(nbody_system) if (param%lextra_force) call tp%accel_user(nbody_system, param, t, lbeg) if (param%lgr) call tp%accel_gr(param) end associate diff --git a/swiftest/__init__.py b/swiftest/__init__.py index 83a324265..6227cef1f 100644 --- a/swiftest/__init__.py +++ b/swiftest/__init__.py @@ -11,4 +11,4 @@ from .constants import * from .simulation_class import Simulation -from .sph_harmonics import Sph_Harmonics \ No newline at end of file +from .shgrav import clm_from_ellipsoid, clm_from_relief \ No newline at end of file diff --git a/swiftest/init_cond.py b/swiftest/init_cond.py index a8770328a..889780a03 100644 --- a/swiftest/init_cond.py +++ b/swiftest/init_cond.py @@ -363,6 +363,16 @@ def solar_system_horizons(name: str, if param['ROTATION']: Ip = Ipsun rot = rotcb + if param['IN_FORM'] == 'XV': + rh = np.array([0.0, 0.0, 0.0]) + vh = np.array([0.0, 0.0, 0.0]) + elif param['IN_FORM'] == 'EL': + a = np.nan + e = np.nan + inc = np.nan + capom = np.nan + omega = np.nan + capm = np.nan else: # Fetch solar system ephemerides from Horizons if ephemeris_id is None: ephemeris_id = name diff --git a/swiftest/io.py b/swiftest/io.py index 33fdb1e8f..4628fe17a 100644 --- a/swiftest/io.py +++ b/swiftest/io.py @@ -858,9 +858,15 @@ def select_active_from_frame(ds, param, framenum=-1): # Select only the active particles at this time step # Remove the inactive particles if param['OUT_FORM'] == 'XV' or param['OUT_FORM'] == 'XVEL': - iactive = iframe[count_dim].where((~np.isnan(iframe['Gmass'])) | (~np.isnan(iframe['rh'].isel(space=0))), drop=True)[count_dim] + if 'rh' in iframe: + iactive = iframe[count_dim].where((~np.isnan(iframe['Gmass'])) | (~np.isnan(iframe['rh'].isel(space=0))), drop=True)[count_dim] + else: + iactive = iframe[count_dim].where(~np.isnan(iframe['Gmass'])) else: - iactive = iframe[count_dim].where((~np.isnan(iframe['Gmass'])) | (~np.isnan(iframe['a'])), drop = True)[count_dim] + if 'a' in iframe: + iactive = iframe[count_dim].where((~np.isnan(iframe['Gmass'])) | (~np.isnan(iframe['a'])), drop = True)[count_dim] + else: + iactive = iframe[count_dim].where(~np.isnan(iframe['Gmass'])) if count_dim == "id": frame = frame.sel(id=iactive.values) elif count_dim == "name": diff --git a/swiftest/shgrav.py b/swiftest/shgrav.py new file mode 100644 index 000000000..6664b3941 --- /dev/null +++ b/swiftest/shgrav.py @@ -0,0 +1,150 @@ +""" + Copyright 2024 - Minton Group at Purdue University + This file is part of Swiftest. + Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with Swiftest. + If not, see: https://www.gnu.org/licenses. +""" + +# python functions to read in and set up spherical harmonics coefficients for non-standard gravity terms +# using pySHTOOLS see: https://shtools.github.io/SHTOOLS/ +# + +from .constants import GC + +try: + import pyshtools as pysh + PYSHTOOLS_AVAILABLE = True +except ModuleNotFoundError: + PYSHTOOLS_AVAILABLE = False + print("pyshtools is not installed. Some features will be unavailable.") + +if PYSHTOOLS_AVAILABLE: + + def clm_from_ellipsoid(mass, density, a, b = None, c = None, lmax = 6, lref_radius = False, ref_radius = None): + """ + Creates and returns the gravity coefficients for an ellipsoid with principal axes a, b, c upto a certain maximum degree lmax. + Uses pyshtools. No units necessary for a, b, & c. However, they need to be in the same units (DU). + + Parameters + ---------- + mass : float + mass of the central body + density : float + density of the central body + a : float + length of the pricipal axis aligned with the x axis + b : float, optional, default = a + length of the pricipal axis aligned with the y axis + c : float, optional, default = b + length of the pricipal axis aligned with the z axis + lmax : int, optional, default = 6 + The maximum spherical harmonic degree resolvable by the grid. + lref_radius : boolean, optional, default = False + Boolean value to return the reference radius calculated by SHTOOLS + ref_radius : float, optional, default = None + Reference radius to scale the gravitational coefficients to + + Returns + ------- + clm : ndarry, shape (2, lmax+1, lmax+1) + numpy ndarray of the gravitational potential spherical harmonic coefficients. + This is a three-dimensional array formatted as coeffs[i, degree, order], + where i=0 corresponds to positive orders and i=1 to negative orders. + + """ + Gmass = GC * mass # SHTOOLS uses an SI G value, and divides it before using the mass; NO NEED TO CHANGE UNITS + + # cap lmax to ensure fast performance without giving up accuracy + lmax_limit = 6 # lmax_limit = 6 derived from Jean's Law; characteristic wavelength = the radius of the CB + if(lmax > lmax_limit): + lmax = lmax_limit + print(f'Setting maximum spherical harmonic degree to {lmax_limit}') + + # create shape grid + shape_SH = pysh.SHGrid.from_ellipsoid(lmax = lmax, a = a, b = b, c = c) + + # get gravity coefficients + clm_class = pysh.SHGravCoeffs.from_shape(shape_SH, rho = density, gm = Gmass) # 4pi normalization + clm = clm_class.to_array(normalization = '4pi') # export as array with 4pi normalization and not scaling by 4*pi to match normalisation + + # Return reference radius EQUALS the radius of the Central Body + print(f'Ensure that the Central Body radius equals the reference radius.') + + if(lref_radius == True and ref_radius is None): + ref_radius = shape_SH.expand(normalization = '4pi').coeffs[0, 0, 0] + return clm, ref_radius + elif(lref_radius == True and ref_radius is not None): + clm_class = clm_class.change_ref(r0 = ref_radius) + clm = clm_class.to_array(normalization = '4pi') + return clm, ref_radius + else: + return clm + + def clm_from_relief(mass, density, grid, lmax = 6, lref_radius = False, ref_radius = None): + """ + Creates and returns the gravity coefficients for a body with a given DH grid upto a certain maximum degree lmax. + Uses pyshtools. + + Parameters + ---------- + mass : float + mass of the central body + density : float + density of the central body + grid : array, shape [] + DH grid of the surface relief of the body + lmax : int, optional, default = 6 + The maximum spherical harmonic degree resolvable by the grid. + lref_radius : boolean, optional, default = False + Boolean value to return the reference radius calculated by SHTOOLS + ref_radius : float, optional, default = None + Reference radius to scale the gravitational coefficients to + + Returns + ------- + clm : ndarry, shape (2, lmax+1, lmax+1) + numpy ndarray of the gravitational potential spherical harmonic coefficients. + This is a three-dimensional array formatted as coeffs[i, degree, order], + where i=0 corresponds to positive orders and i=1 to negative orders. + + """ + + Gmass = GC * mass # SHTOOLS uses an SI G value, and divides it before using the mass; NO NEED TO CHANGE UNITS + + # cap lmax to 20 to ensure fast performance + lmax_limit = 6 + if(lmax > lmax_limit): # FIND A BETTER WAY to judge this cut off point, i.e., relative change between coefficients + lmax = lmax_limit + print(f'Setting maximum spherical harmonic degree to {lmax_limit}') + + # convert to spherical harmonics + shape_SH = pysh.SHGrid.from_array(grid) + + # get coefficients + clm_class = pysh.SHGravcoeffs.from_shape(shape_SH, rho = density, gm = Gmass) # 4pi normalization + clm = clm_class.to_array(normalization = '4pi') # export as array with 4pi normalization + + # Return reference radius EQUALS the radius of the Central Body + + print(f'Ensure that the Central Body radius equals the reference radius.') + + if(lref_radius == True and ref_radius is None): + ref_radius = shape_SH.expand(normalization = '4pi').coeffs[0, 0, 0] + return clm, ref_radius + elif(lref_radius == True and ref_radius is not None): + clm_class = clm_class.change_ref(r0 = ref_radius) + clm = clm_class.to_array(normalization = '4pi') + return clm, ref_radius + else: + return clm + +else: + def clm_from_ellipsoid(*args, **kwargs): + raise NotImplementedError("Sph_Harmonics is not available because pyshtools is not installed.") + def clm_from_relief(*args, **kwargs): + raise NotImplementedError("Sph_Harmonics is not available because pyshtools is not installed.") + \ No newline at end of file diff --git a/swiftest/simulation_class.py b/swiftest/simulation_class.py index d4e3a4e0f..abc552072 100644 --- a/swiftest/simulation_class.py +++ b/swiftest/simulation_class.py @@ -450,6 +450,7 @@ def run(self, # Save initial conditions if not self.restart: self.clean() + self.save() # Write out the current parameter set before executing run self.write_param(verbose=False,**kwargs) @@ -2423,10 +2424,10 @@ def add_body(self, rhill: float | List[float] | npt.NDArray[np.float_] | None=None, rot: List[float] | List[npt.NDArray[np.float_]] | npt.NDArray[np.float_] | None=None, Ip: List[float] | npt.NDArray[np.float_] | None=None, + rotphase: float | List[float] | npt.NDArray[np.float_] | None=None, J2: float | List[float] | npt.NDArray[np.float_] | None=None, J4: float | List[float] | npt.NDArray[np.float_] | None=None, c_lm: List[float] | List[npt.NDArray[np.float_]] | npt.NDArray[np.float_] | None = None, - rotphase: float | List[float] | npt.NDArray[np.float_] | None=None, align_to_central_body_rotation: bool = False, **kwargs: Any ) -> None: @@ -2472,7 +2473,13 @@ def add_body(self, Ip : (3) or (n,3) array-like of float, optional Principal axes moments of inertia vectors if these are massive bodies with rotation enabled. rotphase : float, optional - rotation phase angle of the central body in degrees + rotation phase angle in degreesif these are massive bodies with rotation enabled + J2 : float, optional + Normalized J2 values (e.g. J2*R**2, where R is the central body radius) if this is a central body (only one of J2 or c_lm can be passed) + J4 : float, optional + Normalized J4 values (e.g. J4*R**4, where R is the central body radius) if this is a central body (only one of J4 or c_lm can be passed) + c_lm : (2,l_max+1,l_max+1) array-like of float, optional + Spherical harmonics coefficients if this is a central body (only one of J2/J4 or c_lm can be passed) align_to_central_body_rotation : bool, default False If True, the cartesian coordinates will be aligned to the rotation pole of the central body. This is only valid for when rotation is enabled. @@ -2606,7 +2613,43 @@ def input_to_clm_array(val, n): raise ValueError("Cannot use mass and Gmass inputs simultaneously!") else: Gmass = self.GU * mass - + + is_central_body = False + if J2 is not None or J4 is not None: + is_central_body = True + if c_lm is not None: + raise ValueError("Cannot use J2/J4 and c_lm inputs simultaneously!") + if c_lm is not None: + is_central_body = True + if J2 is not None or J4 is not None: + raise ValueError("Cannot use J2/J4 and c_lm inputs simultaneously!") + + if rh is not None and vh is None: + raise ValueError("If rh is passed, vh must also be passed") + if vh is not None and rh is None: + raise ValueError("If vh is passed, rh must also be passed") + + if rh is not None: + if a is not None or e is not None or inc is not None or capom is not None or omega is not None or capm is not None: + raise ValueError("Only cartesian values or orbital elements may be passed, but not both.") + if is_central_body: + if a is not None or e is not None or inc is not None or capom is not None or omega is not None or capm is not None: + raise ValueError("Orbital elements cannot be passed for a central body.") + if nbodies > 1: + raise ValueError("Only one central body may be passed.") + if self.param['IN_FORM'] == "XV": + if rh is None: + rh = np.zeros((1,3)) + if vh is None: + vh = np.zeros((1,3)) + elif self.param['IN_FORM'] == "EL": + a = np.array([np.nan]) + e = np.array([np.nan]) + inc = np.array([np.nan]) + capom = np.array([np.nan]) + omega = np.array([np.nan]) + capm = np.array([np.nan]) + dsnew = init_cond.vec2xr(self.param, name=name, a=a, e=e, inc=inc, capom=capom, omega=omega, capm=capm, id=id, Gmass=Gmass, radius=radius, rhill=rhill, Ip=Ip, rh=rh, vh=vh,rot=rot, j2rp2=J2, j4rp4=J4, c_lm=c_lm, rotphase=rotphase, time=time) diff --git a/swiftest/sph_harmonics.py b/swiftest/sph_harmonics.py deleted file mode 100644 index 140d35e2b..000000000 --- a/swiftest/sph_harmonics.py +++ /dev/null @@ -1,162 +0,0 @@ -""" - Copyright 2023 - David Minton, Carlisle Wishard, Jennifer Pouplin, Jake Elliott, Dana Singh, & Kaustub Anand - This file is part of Swiftest. - Swiftest is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License - as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - Swiftest is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with Swiftest. - If not, see: https://www.gnu.org/licenses. -""" - -# python functions to read in and set up spherical harmonics coefficients for non-standard gravity terms -# using pySHTOOLS (in python) by Mark W. -# - -import swiftest -import numpy as np -from astroquery.jplhorizons import Horizons -import astropy.units as u -from astropy.coordinates import SkyCoord -import datetime -import xarray as xr -from typing import ( - Literal, - Dict, - List, - Any -) - -try: - import pyshtools as pysh - PYSHTOOLS_AVAILABLE = True -except ModuleNotFoundError: - PYSHTOOLS_AVAILABLE = False - print("pyshtools is not installed. Some features will be unavailable.") - -if PYSHTOOLS_AVAILABLE: - - class Sph_Harmonics(object): - def clm_from_ellipsoid(mass, density, a, b = None, c = None, lmax = 6, lref_radius = False, ref_radius = None): - """ - Creates and returns the gravity coefficients for an ellipsoid with principal axes a, b, c upto a certain maximum degree lmax. - Uses pyshtools. No units necessary for a, b, & c. However, they need to be in the same units (DU). - - Parameters - ---------- - mass : float - mass of the central body - density : float - density of the central body - a : float - length of the pricipal axis aligned with the x axis - b : float, optional, default = a - length of the pricipal axis aligned with the y axis - c : float, optional, default = b - length of the pricipal axis aligned with the z axis - lmax : int, optional, default = 6 - The maximum spherical harmonic degree resolvable by the grid. - lref_radius : boolean, optional, default = False - Boolean value to return the reference radius calculated by SHTOOLS - ref_radius : float, optional, default = None - Reference radius to scale the gravitational coefficients to - - Returns - ------- - clm : ndarry, shape (2, lmax+1, lmax+1) - numpy ndarray of the gravitational potential spherical harmonic coefficients. - This is a three-dimensional array formatted as coeffs[i, degree, order], - where i=0 corresponds to positive orders and i=1 to negative orders. - - """ - Gmass = swiftest.constants.GC * mass # SHTOOLS uses an SI G value, and divides it before using the mass; NO NEED TO CHANGE UNITS - - # cap lmax to ensure fast performance without giving up accuracy - lmax_limit = 6 # lmax_limit = 6 derived from Jean's Law; characteristic wavelength = the radius of the CB - if(lmax > lmax_limit): - lmax = lmax_limit - print(f'Setting maximum spherical harmonic degree to {lmax_limit}') - - # create shape grid - shape_SH = pysh.SHGrid.from_ellipsoid(lmax = lmax, a = a, b = b, c = c) - - # get gravity coefficients - clm_class = pysh.SHGravCoeffs.from_shape(shape_SH, rho = density, gm = Gmass) # 4pi normalization - clm = clm_class.to_array(normalization = '4pi') # export as array with 4pi normalization and not scaling by 4*pi to match normalisation - - # Return reference radius EQUALS the radius of the Central Body - print(f'Ensure that the Central Body radius equals the reference radius.') - - if(lref_radius == True and ref_radius is None): - ref_radius = shape_SH.expand(normalization = '4pi').coeffs[0, 0, 0] - return clm, ref_radius - elif(lref_radius == True and ref_radius is not None): - clm_class = clm_class.change_ref(r0 = ref_radius) - clm = clm_class.to_array(normalization = '4pi') - return clm, ref_radius - else: - return clm - - def clm_from_relief(mass, density, grid, lmax = 6, lref_radius = False, ref_radius = None): - """ - Creates and returns the gravity coefficients for a body with a given DH grid upto a certain maximum degree lmax. - Uses pyshtools. - - Parameters - ---------- - mass : float - mass of the central body - density : float - density of the central body - grid : array, shape [] - DH grid of the surface relief of the body - lmax : int, optional, default = 6 - The maximum spherical harmonic degree resolvable by the grid. - lref_radius : boolean, optional, default = False - Boolean value to return the reference radius calculated by SHTOOLS - ref_radius : float, optional, default = None - Reference radius to scale the gravitational coefficients to - - Returns - ------- - clm : ndarry, shape (2, lmax+1, lmax+1) - numpy ndarray of the gravitational potential spherical harmonic coefficients. - This is a three-dimensional array formatted as coeffs[i, degree, order], - where i=0 corresponds to positive orders and i=1 to negative orders. - - """ - - Gmass = swiftest.constants.GC * mass # SHTOOLS uses an SI G value, and divides it before using the mass; NO NEED TO CHANGE UNITS - - # cap lmax to 20 to ensure fast performance - lmax_limit = 6 - if(lmax > lmax_limit): # FIND A BETTER WAY to judge this cut off point, i.e., relative change between coefficients - lmax = lmax_limit - print(f'Setting maximum spherical harmonic degree to {lmax_limit}') - - # convert to spherical harmonics - shape_SH = pysh.SHGrid.from_array(grid) - - # get coefficients - clm_class = pysh.SHGravcoeffs.from_shape(shape_SH, rho = density, gm = Gmass) # 4pi normalization - clm = clm_class.to_array(normalization = '4pi') # export as array with 4pi normalization - - # Return reference radius EQUALS the radius of the Central Body - - print(f'Ensure that the Central Body radius equals the reference radius.') - - if(lref_radius == True and ref_radius is None): - ref_radius = shape_SH.expand(normalization = '4pi').coeffs[0, 0, 0] - return clm, ref_radius - elif(lref_radius == True and ref_radius is not None): - clm_class = clm_class.change_ref(r0 = ref_radius) - clm = clm_class.to_array(normalization = '4pi') - return clm, ref_radius - else: - return clm - -else: - class Sph_Harmonics(object): - def clm_from_ellipsoid(*args, **kwargs): - raise NotImplementedError("Sph_Harmonics is not available because pyshtools is not installed.") - \ No newline at end of file