From bcb2f461e04b1463bc62781235ea53e05b1d4cd6 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 28 Jul 2021 01:36:49 -0400 Subject: [PATCH] Added new methods for sorting bodies in various ways --- src/modules/swiftest_classes.f90 | 125 ++++++++++------ src/util/util_sort.f90 | 236 +++++++++++++++++++++++++++++-- 2 files changed, 304 insertions(+), 57 deletions(-) diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index fe9b7e86d..7f91f93f2 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -21,7 +21,9 @@ module swiftest_classes public :: user_kick_getacch_body public :: util_coord_b2h_pl, util_coord_b2h_tp, util_coord_h2b_pl, util_coord_h2b_tp, util_exit, util_fill_body, util_fill_pl, util_fill_tp, & util_peri_tp, util_reverse_status, util_set_beg_end_pl, util_set_ir3h, util_set_msys, util_set_mu_pl, & - util_set_mu_tp, util_set_rhill, util_set_rhill_approximate, util_sort, util_sort_body, util_spill_body, util_spill_pl, util_spill_tp, util_valid, util_version + util_set_mu_tp, util_set_rhill, util_set_rhill_approximate, & + util_sort, util_sort_body, util_sort_pl, util_sort_tp, util_sort_rearrange_body, util_sort_rearrange_pl, util_sort_rearrange_tp, & + util_spill_body, util_spill_pl, util_spill_tp, util_valid, util_version !******************************************************************************************************************************** ! swiftest_parameters class definitions @@ -130,8 +132,8 @@ module swiftest_classes contains private procedure, public :: initialize => io_read_cb_in !! I/O routine for reading in central body data - procedure, public :: write_frame => io_write_frame_cb !! I/O routine for writing out a single frame of time-series data for the central body procedure, public :: read_frame => io_read_frame_cb !! I/O routine for reading out a single frame of time-series data for the central body + procedure, public :: write_frame => io_write_frame_cb !! I/O routine for writing out a single frame of time-series data for the central body end type swiftest_cb !******************************************************************************************************************************** @@ -172,22 +174,23 @@ module swiftest_classes procedure(abstract_step_body), public, deferred :: step procedure(abstract_accel), public, deferred :: accel ! These are concrete because the implementation is the same for all types of particles - procedure, public :: drift => drift_body !! Loop through bodies and call Danby drift routine on heliocentric variables - procedure, public :: v2pv => gr_vh2pv_body !! Converts from velocity to psudeovelocity for GR calculations using symplectic integrators - procedure, public :: pv2v => gr_pv2vh_body !! Converts from psudeovelocity to velocity for GR calculations using symplectic integrators - procedure, public :: initialize => io_read_body_in !! Read in body initial conditions from a file - procedure, public :: read_frame => io_read_frame_body !! I/O routine for writing out a single frame of time-series data for the central body - procedure, public :: write_frame => io_write_frame_body !! I/O routine for writing out a single frame of time-series data for the central body - procedure, public :: accel_obl => obl_acc_body !! Compute the barycentric accelerations of bodies due to the oblateness of the central body - procedure, public :: el2xv => orbel_el2xv_vec !! Convert orbital elements to position and velocity vectors - procedure, public :: xv2el => orbel_xv2el_vec !! Convert position and velocity vectors to orbital elements - procedure, public :: set_ir3 => util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) - procedure, public :: setup => setup_body !! A constructor that sets the number of bodies and allocates all allocatable arrays + procedure, public :: drift => drift_body !! Loop through bodies and call Danby drift routine on heliocentric variables + procedure, public :: v2pv => gr_vh2pv_body !! Converts from velocity to psudeovelocity for GR calculations using symplectic integrators + procedure, public :: pv2v => gr_pv2vh_body !! Converts from psudeovelocity to velocity for GR calculations using symplectic integrators + procedure, public :: initialize => io_read_body_in !! Read in body initial conditions from a file + procedure, public :: read_frame => io_read_frame_body !! I/O routine for writing out a single frame of time-series data for the central body + procedure, public :: write_frame => io_write_frame_body !! I/O routine for writing out a single frame of time-series data for the central body + procedure, public :: accel_obl => obl_acc_body !! Compute the barycentric accelerations of bodies due to the oblateness of the central body + procedure, public :: el2xv => orbel_el2xv_vec !! Convert orbital elements to position and velocity vectors + procedure, public :: xv2el => orbel_xv2el_vec !! Convert position and velocity vectors to orbital elements + procedure, public :: setup => setup_body !! A constructor that sets the number of bodies and allocates all allocatable arrays procedure, public :: accel_user => user_kick_getacch_body !! Add user-supplied heliocentric accelerations to planets - procedure, public :: fill => util_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) - procedure, public :: spill => util_spill_body !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) - procedure, public :: sort => util_sort_body !! Sorts a body by an attribute (base method only allows for sorting by id. Override to add other capabilities) - procedure, public :: reverse_status => util_reverse_status !! Reverses the active/inactive status of all particles in a structure + procedure, public :: fill => util_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure, public :: reverse_status => util_reverse_status !! Reverses the active/inactive status of all particles in a structure + procedure, public :: set_ir3 => util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) + procedure, public :: sort => util_sort_body !! Sorts body arrays by a sortable componen + procedure, public :: rearrange => util_sort_rearrange_body !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure, public :: spill => util_spill_body !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type swiftest_body !******************************************************************************************************************************** @@ -217,19 +220,21 @@ module swiftest_classes private ! Massive body-specific concrete methods ! These are concrete because they are the same implemenation for all integrators - procedure, public :: discard => discard_pl !! Placeholder method for discarding massive bodies - procedure, public :: eucl_index => eucl_dist_index_plpl !! Sets up the (i, j) -> k indexing used for the single-loop blocking Euclidean distance matrix - procedure, public :: accel_int => kick_getacch_int_pl !! Compute direct cross (third) term heliocentric accelerations of massive bodies - procedure, public :: accel_obl => obl_acc_pl !! Compute the barycentric accelerations of bodies due to the oblateness of the central body - procedure, public :: setup => setup_pl !! A base constructor that sets the number of bodies and allocates and initializes all arrays - procedure, public :: accel_tides => tides_kick_getacch_pl !! Compute the accelerations of bodies due to tidal interactions with the central body - procedure, public :: set_mu => util_set_mu_pl !! Method used to construct the vectorized form of the central body mass - procedure, public :: set_rhill => util_set_rhill !! Calculates the Hill's radii for each body - procedure, public :: h2b => util_coord_h2b_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) - procedure, public :: b2h => util_coord_b2h_pl !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) - procedure, public :: fill => util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) - procedure, public :: set_beg_end => util_set_beg_end_pl !! Sets the beginning and ending positions and velocities of planets. - procedure, public :: spill => util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure, public :: discard => discard_pl !! Placeholder method for discarding massive bodies + procedure, public :: eucl_index => eucl_dist_index_plpl !! Sets up the (i, j) -> k indexing used for the single-loop blocking Euclidean distance matrix + procedure, public :: accel_int => kick_getacch_int_pl !! Compute direct cross (third) term heliocentric accelerations of massive bodies + procedure, public :: accel_obl => obl_acc_pl !! Compute the barycentric accelerations of bodies due to the oblateness of the central body + procedure, public :: setup => setup_pl !! A base constructor that sets the number of bodies and allocates and initializes all arrays + procedure, public :: accel_tides => tides_kick_getacch_pl !! Compute the accelerations of bodies due to tidal interactions with the central body + procedure, public :: h2b => util_coord_h2b_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) + procedure, public :: b2h => util_coord_b2h_pl !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) + procedure, public :: fill => util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure, public :: set_beg_end => util_set_beg_end_pl !! Sets the beginning and ending positions and velocities of planets. + procedure, public :: set_mu => util_set_mu_pl !! Method used to construct the vectorized form of the central body mass + procedure, public :: set_rhill => util_set_rhill !! Calculates the Hill's radii for each body + procedure, public :: sort => util_sort_pl !! Sorts body arrays by a sortable component + procedure, public :: rearrange => util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure, public :: spill => util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type swiftest_pl !******************************************************************************************************************************** @@ -247,16 +252,18 @@ module swiftest_classes private ! Test particle-specific concrete methods ! These are concrete because they are the same implemenation for all integrators - procedure, public :: discard => discard_tp !! Check to see if test particles should be discarded based on their positions relative to the massive bodies - procedure, public :: accel_int => kick_getacch_int_tp !! Compute direct cross (third) term heliocentric accelerations of test particles by massive bodies - procedure, public :: accel_obl => obl_acc_tp !! Compute the barycentric accelerations of bodies due to the oblateness of the central body - procedure, public :: setup => setup_tp !! A base constructor that sets the number of bodies and - procedure, public :: set_mu => util_set_mu_tp !! Method used to construct the vectorized form of the central body mass - procedure, public :: h2b => util_coord_h2b_tp !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) - procedure, public :: b2h => util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) - procedure, public :: fill => util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) - procedure, public :: get_peri => util_peri_tp !! Determine system pericenter passages for test particles - procedure, public :: spill => util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure, public :: discard => discard_tp !! Check to see if test particles should be discarded based on their positions relative to the massive bodies + procedure, public :: accel_int => kick_getacch_int_tp !! Compute direct cross (third) term heliocentric accelerations of test particles by massive bodies + procedure, public :: accel_obl => obl_acc_tp !! Compute the barycentric accelerations of bodies due to the oblateness of the central body + procedure, public :: setup => setup_tp !! A base constructor that sets the number of bodies and + procedure, public :: h2b => util_coord_h2b_tp !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) + procedure, public :: b2h => util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) + procedure, public :: fill => util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure, public :: get_peri => util_peri_tp !! Determine system pericenter passages for test particles + procedure, public :: set_mu => util_set_mu_tp !! Method used to construct the vectorized form of the central body mass + procedure, public :: sort => util_sort_tp !! Sorts body arrays by a sortable component + procedure, public :: rearrange => util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure, public :: spill => util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type swiftest_tp !******************************************************************************************************************************** @@ -289,10 +296,10 @@ module swiftest_classes ! Concrete classes that are common to the basic integrator (only test particles considered for discard) procedure, public :: discard => discard_system !! Perform a discard step on the system procedure, public :: dump => io_dump_system !! Dump the state of the system to a file - procedure, public :: initialize => setup_initialize_system !! Initialize the system from input files procedure, public :: read_frame => io_read_frame_system !! Append a frame of output data to file procedure, public :: write_discard => io_write_discard !! Append a frame of output data to file procedure, public :: write_frame => io_write_frame_system !! Append a frame of output data to file + procedure, public :: initialize => setup_initialize_system !! Initialize the system from input files procedure, public :: step_spin => tides_step_spin_system !! Steps the spins of the massive & central bodies due to tides. procedure, public :: set_msys => util_set_msys !! Sets the value of msys from the masses of system bodies. end type swiftest_nbody_system @@ -881,12 +888,44 @@ end subroutine util_sort_index_dp end interface util_sort interface - module subroutine util_sort_body(self, sortby, reverse) + module subroutine 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) + end subroutine util_sort_rearrange_body + + module subroutine 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) + end subroutine util_sort_rearrange_pl + + module subroutine 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) + end subroutine util_sort_rearrange_tp + + module subroutine 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) :: reverse !! Logical flag indicating whether or not the sorting should be in reverse (descending order) + logical, intent(in) :: ascending !! Logical flag indicating whether or not the sorting should be in ascending or descending order end subroutine util_sort_body + + module subroutine 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 + end subroutine util_sort_pl + + module subroutine 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 + end subroutine util_sort_tp module subroutine util_spill_body(self, discards, lspill_list) implicit none diff --git a/src/util/util_sort.f90 b/src/util/util_sort.f90 index 190561002..fdaded124 100644 --- a/src/util/util_sort.f90 +++ b/src/util/util_sort.f90 @@ -1,33 +1,185 @@ submodule (swiftest_classes) s_util_sort use swiftest contains - module subroutine util_sort_body(self, sortby, reverse) + module subroutine util_sort_body(self, sortby, ascending) !! author: David A. Minton !! !! Sort a Swiftest body structure in-place. - !! sortby is a string. The only valid input the body class takes is "id," which is also the default value. - !! Sort order is ascending order by default. Set reverse=.true. to sort in descending order. + !! sortby is a string indicating which array component to sort. implicit none ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest body object - character(*), intent(in) :: sortby !! Sorting attribute - logical, intent(in) :: reverse !! Logical flag indicating whether or not the sorting should be in reverse (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 ! Internals - class(swiftest_body), allocatable :: body_sorted !! Temporary holder for sorted body integer(I4B), dimension(:), allocatable :: ind - associate(n => self%nbody) - allocate(body_sorted, source=self) - allocate(ind(n)) + associate(body => self, n => self%nbody) select case(sortby) case("id") - if (reverse) then - call util_sort(-self%id(1:n), ind(1:n)) + if (ascending) then + call util_sort(body%id(1:n), ind(1:n)) + else + call util_sort(-body%id(1:n), ind(1:n)) + end if + case("a") + if (ascending) then + call util_sort(body%a(1:n), ind(1:n)) + else + call util_sort(-body%a(1:n), ind(1:n)) + end if + case("e") + if (ascending) then + call util_sort(body%e(1:n), ind(1:n)) + else + call util_sort(-body%e(1:n), ind(1:n)) + end if + case("inc") + if (ascending) then + call util_sort(body%inc(1:n), ind(1:n)) + else + call util_sort(-body%inc(1:n), ind(1:n)) + end if + case("capom") + if (ascending) then + call util_sort(body%capom(1:n), ind(1:n)) + else + call util_sort(-body%capom(1:n), ind(1:n)) + end if + case("mu") + if (ascending) then + call util_sort(body%mu(1:n), ind(1:n)) + else + call util_sort(-body%mu(1:n), ind(1:n)) + end if + case default + write(*,*) 'Cannot sort structure by component '//trim(adjustl(sortby)) + end select + + call body%rearrange(ind) + end associate + + return + end subroutine util_sort_body + + module subroutine util_sort_pl(self, sortby, ascending) + !! author: David A. Minton + !! + !! Sort a Swiftest massive body object in-place. + !! sortby is a string indicating which array component to sort. + implicit none + ! Arguments + class(swiftest_pl), intent(inout) :: self !! Swiftest 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 + + associate(pl => self, npl => self%nbody) + select case(sortby) + case("Gmass","mass") + if (ascending) then + call util_sort(pl%Gmass(1:npl), ind(1:npl)) + else + call util_sort(-pl%Gmass(1:npl), ind(1:npl)) + end if + case("rhill") + if (ascending) then + call util_sort(pl%rhill(1:npl), ind(1:npl)) + else + call util_sort(-pl%rhill(1:npl), ind(1:npl)) + end if + case("radius") + if (ascending) then + call util_sort(pl%radius(1:npl), ind(1:npl)) + else + call util_sort(-pl%radius(1:npl), ind(1:npl)) + end if + case("density") + if (ascending) then + call util_sort(pl%density(1:npl), ind(1:npl)) else - call util_sort(self%id(1:n), ind(1:n)) + call util_sort(-pl%density(1:npl), ind(1:npl)) end if + case("k2") + if (ascending) then + call util_sort(pl%k2(1:npl), ind(1:npl)) + else + call util_sort(-pl%k2(1:npl), ind(1:npl)) + end if + case("Q") + if (ascending) then + call util_sort(pl%Q(1:npl), ind(1:npl)) + else + call util_sort(-pl%Q(1:npl), ind(1:npl)) + end if + case("tlag") + if (ascending) then + call util_sort(pl%tlag(1:npl), ind(1:npl)) + else + call util_sort(-pl%tlag(1:npl), ind(1:npl)) + end if + case default + call util_sort_body(pl, sortby, ascending) end select + call pl%rearrange(ind) + end associate + + return + end subroutine util_sort_pl + + module subroutine util_sort_tp(self, sortby, ascending) + !! author: David A. Minton + !! + !! Sort a Swiftest test particle object in-place. + !! sortby is a string indicating which array component to sort. + implicit none + ! Arguments + class(swiftest_tp), intent(inout) :: self !! Swiftest 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 + + associate(tp => self, ntp => self%nbody) + select case(sortby) + case("peri") + if (ascending) then + call util_sort(tp%peri(1:ntp), ind(1:ntp)) + else + call util_sort(-tp%peri(1:ntp), ind(1:ntp)) + end if + case("atp") + if (ascending) then + call util_sort(tp%atp(1:ntp), ind(1:ntp)) + else + call util_sort(-tp%atp(1:ntp), ind(1:ntp)) + end if + case default + call util_sort_body(tp, sortby, ascending) + end select + + call tp%rearrange(ind) + end associate + + return + end subroutine util_sort_tp + + module subroutine util_sort_rearrange_body(self, ind) + !! author: David A. Minton + !! + !! Rearrange Swiftest body structure in-place from an index list. + !! This is a helper utility used to make polymorphic sorting work on Swiftest structures. + implicit none + ! Arguments + 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) + ! Internals + class(swiftest_body), allocatable :: body_sorted !! Temporary holder for sorted body + + associate(n => self%nbody) + allocate(body_sorted, source=self) self%id(1:n) = body_sorted%id(ind(1:n)) self%name(1:n) = body_sorted%name(ind(1:n)) self%status(1:n) = body_sorted%status(ind(1:n)) @@ -48,9 +200,65 @@ module subroutine util_sort_body(self, sortby, reverse) self%omega(1:n) = body_sorted%omega(ind(1:n)) self%capm(1:n) = body_sorted%capm(ind(1:n)) self%mu(1:n) = body_sorted%mu(ind(1:n)) + deallocate(body_sorted) end associate return - end subroutine util_sort_body + end subroutine util_sort_rearrange_body + + module subroutine util_sort_rearrange_pl(self, ind) + !! author: David A. Minton + !! + !! Rearrange Swiftest massive body structure in-place from an index list. + !! This is a helper utility used to make polymorphic sorting work on Swiftest structures. + 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) + ! Internals + class(swiftest_pl), allocatable :: pl_sorted !! Temporary holder for sorted body + + call util_sort_rearrange_body(self,ind) + associate(n => self%nbody) + allocate(pl_sorted, source=self) + self%mass(1:n) = pl_sorted%mass(ind(1:n)) + self%Gmass(1:n) = pl_sorted%Gmass(ind(1:n)) + self%rhill(1:n) = pl_sorted%rhill(ind(1:n)) + self%radius(1:n) = pl_sorted%radius(ind(1:n)) + self%xbeg(:,1:n) = pl_sorted%xbeg(:,ind(1:n)) + self%xend(:,1:n) = pl_sorted%xend(:,ind(1:n)) + self%vbeg(:,1:n) = pl_sorted%vbeg(:,ind(1:n)) + self%density(1:n) = pl_sorted%density(ind(1:n)) + self%Ip(:,1:n) = pl_sorted%Ip(:,ind(1:n)) + self%rot(:,1:n) = pl_sorted%rot(:,ind(1:n)) + self%k2(1:n) = pl_sorted%k2(ind(1:n)) + self%Q(1:n) = pl_sorted%Q(ind(1:n)) + self%tlag(1:n) = pl_sorted%tlag(ind(1:n)) + deallocate(pl_sorted) + end associate + return + end subroutine util_sort_rearrange_pl + + module subroutine util_sort_rearrange_tp(self, ind) + !! author: David A. Minton + !! + !! Rearrange Swiftest massive body structure in-place from an index list. + !! This is a helper utility used to make polymorphic sorting work on Swiftest structures. + implicit none + ! Arguments + 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) + ! Internals + class(swiftest_tp), allocatable :: tp_sorted !! Temporary holder for sorted body + + call util_sort_rearrange_body(self,ind) + associate(n => self%nbody) + allocate(tp_sorted, source=self) + self%isperi(1:n) = tp_sorted%isperi(ind(1:n)) + self%peri(1:n) = tp_sorted%peri(ind(1:n)) + self%atp(1:n) = tp_sorted%atp(ind(1:n)) + deallocate(tp_sorted) + end associate + return + end subroutine util_sort_rearrange_tp module subroutine util_sort_dp(arr) !! author: David A. Minton