From 19b6a87d54a138ecf99d71d9332e9f61cb9b433e Mon Sep 17 00:00:00 2001 From: David Minton Date: Sat, 31 Jul 2021 07:53:39 -0400 Subject: [PATCH 01/42] Added copy and resize methods to swiftest_body Changed the setup method so that it deallocates previously allocated arrays, and started the process of adding copy and resize methods --- src/modules/swiftest_classes.f90 | 16 +++++++++++++ src/rmvs/rmvs_setup.f90 | 6 +++++ src/setup/setup.f90 | 31 +++++++++++++++++++++++++ src/symba/symba_setup.f90 | 22 ++++++++++++++++++ src/util/util_copy.f90 | 19 +++++++++++++++ src/util/util_resize.f90 | 40 ++++++++++++++++++++++++++++++++ src/util/util_spill_and_fill.f90 | 2 +- src/whm/whm_setup.f90 | 6 +++++ 8 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 src/util/util_copy.f90 create mode 100644 src/util/util_resize.f90 diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 913d678eb..64a6e8778 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -164,7 +164,9 @@ module swiftest_classes procedure :: xv2el => orbel_xv2el_vec !! Convert position and velocity vectors to orbital elements procedure :: setup => setup_body !! A constructor that sets the number of bodies and allocates all allocatable arrays procedure :: accel_user => user_kick_getacch_body !! Add user-supplied heliocentric accelerations to planets + procedure :: copy => util_copy_body !! Copies elements from one structure to another procedure :: fill => util_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: resize => 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 => util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) procedure :: sort => util_sort_body !! Sorts body arrays by a sortable componen procedure :: rearrange => util_sort_rearrange_body !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods @@ -757,6 +759,13 @@ module subroutine util_coord_h2b_tp(self, cb) class(swiftest_cb), intent(in) :: cb !! Swiftest central body object end subroutine util_coord_h2b_tp + module subroutine util_copy_body(self, source, param) + implicit none + class(swiftest_body), intent(inout) :: self !! Swiftest body object + class(swiftest_body), intent(in) :: source !! Source object to copy + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + end subroutine util_copy_body + module subroutine util_exit(code) implicit none integer(I4B), intent(in) :: code !! Failure exit code @@ -790,6 +799,13 @@ module subroutine util_peri_tp(self, system, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters end subroutine util_peri_tp + module subroutine util_resize_body(self, nrequested, param) + implicit none + class(swiftest_body), intent(inout) :: self !! Swiftest body object + integer(I4B), intent(in) :: nrequested !! New size neded + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + end subroutine util_resize_body + module subroutine util_set_beg_end_pl(self, xbeg, xend, vbeg) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object diff --git a/src/rmvs/rmvs_setup.f90 b/src/rmvs/rmvs_setup.f90 index 778ba3714..92043e0fe 100644 --- a/src/rmvs/rmvs_setup.f90 +++ b/src/rmvs/rmvs_setup.f90 @@ -147,10 +147,16 @@ module subroutine rmvs_setup_tp(self, n, param) call setup_tp(self, n, param) if (n <= 0) return + if (allocated(self%lperi)) deallocate(self%lperi) + if (allocated(self%plperP)) deallocate(self%plperP) + if (allocated(self%plencP)) deallocate(self%plencP) + allocate(self%lperi(n)) allocate(self%plperP(n)) allocate(self%plencP(n)) + if (self%lplanetocentric) then + if (allocated(self%xheliocentric)) deallocate(self%xheliocentric) allocate(self%xheliocentric(NDIM, n)) end if diff --git a/src/setup/setup.f90 b/src/setup/setup.f90 index 50da6ce1c..f1e44f19c 100644 --- a/src/setup/setup.f90 +++ b/src/setup/setup.f90 @@ -110,6 +110,19 @@ module subroutine setup_body(self, n, param) if (n <= 0) return self%lfirst = .true. + if (allocated(self%id)) deallocate(self%id) + if (allocated(self%name)) deallocate(self%name) + if (allocated(self%status)) deallocate(self%status) + if (allocated(self%ldiscard)) deallocate(self%ldiscard) + if (allocated(self%xh)) deallocate(self%xh) + if (allocated(self%vh)) deallocate(self%vh) + if (allocated(self%xb)) deallocate(self%xb) + if (allocated(self%vb)) deallocate(self%vb) + if (allocated(self%ah)) deallocate(self%ah) + if (allocated(self%ir3h)) deallocate(self%ir3h) + if (allocated(self%mu)) deallocate(self%mu) + if (allocated(self%lmask)) deallocate(self%lmask) + allocate(self%id(n)) allocate(self%name(n)) allocate(self%status(n)) @@ -137,14 +150,17 @@ module subroutine setup_body(self, n, param) self%mu(:) = 0.0_DP if (param%loblatecb) then + if (allocated(self%aobl)) deallocate(self%aobl) allocate(self%aobl(NDIM, n)) self%aobl(:,:) = 0.0_DP end if if (param%ltides) then + if (allocated(self%atide)) deallocate(self%lmask) allocate(self%atide(NDIM, n)) self%atide(:,:) = 0.0_DP end if if (param%lgr) then + if (allocated(self%agr)) deallocate(self%lmask) allocate(self%agr(NDIM, n)) self%agr(:,:) = 0.0_DP end if @@ -169,6 +185,10 @@ module subroutine setup_pl(self, n, param) call setup_body(self, n, param) if (n <= 0) return + if (allocated(self%mass)) deallocate(self%mass) + if (allocated(self%Gmass)) deallocate(self%Gmass) + if (allocated(self%rhill)) deallocate(self%rhill) + allocate(self%mass(n)) allocate(self%Gmass(n)) allocate(self%rhill(n)) @@ -180,6 +200,8 @@ module subroutine setup_pl(self, n, param) self%nplpl = 0 if (param%lclose) then + if (allocated(self%radius)) deallocate(self%radius) + if (allocated(self%density)) deallocate(self%density) allocate(self%radius(n)) allocate(self%density(n)) self%radius(:) = 0.0_DP @@ -187,6 +209,8 @@ module subroutine setup_pl(self, n, param) end if if (param%lrotation) then + if (allocated(self%rot)) deallocate(self%rhill) + if (allocated(self%Ip)) deallocate(self%rhill) allocate(self%rot(NDIM, n)) allocate(self%Ip(NDIM, n)) self%rot(:,:) = 0.0_DP @@ -194,6 +218,9 @@ module subroutine setup_pl(self, n, param) end if if (param%ltides) then + if (allocated(self%k2)) deallocate(self%rhill) + if (allocated(self%Q)) deallocate(self%rhill) + if (allocated(self%tlag)) deallocate(self%rhill) allocate(self%k2(n)) allocate(self%Q(n)) allocate(self%tlag(n)) @@ -222,6 +249,10 @@ module subroutine setup_tp(self, n, param) call setup_body(self, n, param) if (n <= 0) return + if (allocated(self%isperi)) deallocate(self%isperi) + if (allocated(self%peri)) deallocate(self%peri) + if (allocated(self%atp)) deallocate(self%atp) + allocate(self%isperi(n)) allocate(self%peri(n)) allocate(self%atp(n)) diff --git a/src/symba/symba_setup.f90 b/src/symba/symba_setup.f90 index e240be778..dab92f3ca 100644 --- a/src/symba/symba_setup.f90 +++ b/src/symba/symba_setup.f90 @@ -55,6 +55,19 @@ module subroutine symba_setup_pl(self, n, param) call setup_pl(self, n, param) if (n <= 0) return + if (allocated(self%lcollision)) deallocate(self%lcollision) + if (allocated(self%lencounter)) deallocate(self%lencounter) + if (allocated(self%lmtiny)) deallocate(self%lmtiny) + if (allocated(self%nplenc)) deallocate(self%nplenc) + if (allocated(self%ntpenc)) deallocate(self%ntpenc) + if (allocated(self%levelg)) deallocate(self%levelg) + if (allocated(self%levelm)) deallocate(self%levelm) + if (allocated(self%isperi)) deallocate(self%isperi) + if (allocated(self%peri)) deallocate(self%peri) + if (allocated(self%atp)) deallocate(self%atp) + if (allocated(self%kin)) deallocate(self%kin) + if (allocated(self%info)) deallocate(self%info) + allocate(self%lcollision(n)) allocate(self%lencounter(n)) allocate(self%lmtiny(n)) @@ -102,11 +115,13 @@ module subroutine symba_setup_pltpenc(self, n) if (allocated(self%level)) deallocate(self%level) if (allocated(self%index1)) deallocate(self%index1) if (allocated(self%index2)) deallocate(self%index2) + allocate(self%lvdotr(n)) allocate(self%status(n)) allocate(self%level(n)) allocate(self%index1(n)) allocate(self%index2(n)) + self%lvdotr(:) = .false. self%status(:) = INACTIVE self%level(:) = -1 @@ -134,10 +149,12 @@ module subroutine symba_setup_plplenc(self, n) if (allocated(self%xh2)) deallocate(self%xh2) if (allocated(self%vb1)) deallocate(self%vb1) if (allocated(self%vb2)) deallocate(self%vb2) + allocate(self%xh1(NDIM,n)) allocate(self%xh2(NDIM,n)) allocate(self%vb1(NDIM,n)) allocate(self%vb2(NDIM,n)) + self%xh1(:,:) = 0.0_DP self%xh2(:,:) = 0.0_DP self%vb1(:,:) = 0.0_DP @@ -163,9 +180,14 @@ module subroutine symba_setup_tp(self, n, param) call setup_tp(self, n, param) if (n <= 0) return + if (allocated(self%nplenc)) deallocate(self%nplenc) + if (allocated(self%levelg)) deallocate(self%levelg) + if (allocated(self%levelm)) deallocate(self%levelm) + allocate(self%nplenc(n)) allocate(self%levelg(n)) allocate(self%levelm(n)) + self%nplenc(:) = 0 self%levelg(:) = -1 self%levelm(:) = -1 diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 new file mode 100644 index 000000000..fcbd0d5da --- /dev/null +++ b/src/util/util_copy.f90 @@ -0,0 +1,19 @@ +submodule (swiftest_classes) s_util_copy + use swiftest +contains + + module subroutine util_copy_body(self, source, param) + !! author: David A. Minton + !! + !! Non-destructively copy components from one Swiftest body object to another. + !! This method will automatically resize the destination body if it is too small + implicit none + ! Arguments + class(swiftest_body), intent(inout) :: self !! Swiftest body object + class(swiftest_body), intent(in) :: source !! Source object to copy + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + + return + end subroutine util_copy_body + +end submodule s_util_copy \ No newline at end of file diff --git a/src/util/util_resize.f90 b/src/util/util_resize.f90 new file mode 100644 index 000000000..cde0428d4 --- /dev/null +++ b/src/util/util_resize.f90 @@ -0,0 +1,40 @@ +submodule (swiftest_classes) s_util_resize + use swiftest +contains + + module subroutine util_resize_body(self, nrequested, param) + !! author: David A. Minton + !! + !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + implicit none + ! Arguments + class(swiftest_body), intent(inout) :: self !! Swiftest body object + integer(I4B), intent(in) :: nrequested !! New size neded + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + class(swiftest_body), allocatable :: temp + integer(I4B) :: nold + logical :: lmalloc + + lmalloc = allocated(self%status) + if (lmalloc) then + nold = size(self%status) + else + nold = 0 + end if + if (nrequested > nold) then + if (lmalloc) allocate(temp, source=self) + call self%setup(nrequested, param) + if (lmalloc) then + call self%copy(temp, param) + deallocate(temp) + end if + else + self%status(nrequested+1:nold) = INACTIVE + end if + self%nbody = nrequested + + return + end subroutine util_resize_body + +end submodule s_util_resize \ No newline at end of file diff --git a/src/util/util_spill_and_fill.f90 b/src/util/util_spill_and_fill.f90 index 8ea85f654..89f8bb095 100644 --- a/src/util/util_spill_and_fill.f90 +++ b/src/util/util_spill_and_fill.f90 @@ -231,7 +231,7 @@ module subroutine util_spill_pl(self, discards, lspill_list) ! Arguments 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 discardse + logical, dimension(:), intent(in) :: lspill_list !! Logical array of bodies to spill into the discards ! Internals integer(I4B) :: i diff --git a/src/whm/whm_setup.f90 b/src/whm/whm_setup.f90 index 0de03ec2c..cbf36cc90 100644 --- a/src/whm/whm_setup.f90 +++ b/src/whm/whm_setup.f90 @@ -18,6 +18,12 @@ module subroutine whm_setup_pl(self, n, param) call setup_pl(self, n, param) if (n <= 0) return + if (allocated(self%eta)) deallocate(self%eta) + if (allocated(self%muj)) deallocate(self%muj) + if (allocated(self%xj)) deallocate(self%xj) + if (allocated(self%vj)) deallocate(self%vj) + if (allocated(self%ir3j)) deallocate(self%ir3j) + allocate(self%eta(n)) allocate(self%muj(n)) allocate(self%xj(NDIM, n)) From 4bd3487366201dc1cf9698cd78ab3766bfa8f848 Mon Sep 17 00:00:00 2001 From: David Minton Date: Sat, 31 Jul 2021 08:14:44 -0400 Subject: [PATCH 02/42] Added templates for append and copy_into methods --- src/modules/swiftest_classes.f90 | 22 ++++++++++++++++------ src/util/util_append.f90 | 24 ++++++++++++++++++++++++ src/util/util_copy.f90 | 24 ++++++++++++++++++------ src/util/util_resize.f90 | 2 +- 4 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 src/util/util_append.f90 diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 64a6e8778..ac7639bc4 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -164,7 +164,8 @@ module swiftest_classes procedure :: xv2el => orbel_xv2el_vec !! Convert position and velocity vectors to orbital elements procedure :: setup => setup_body !! A constructor that sets the number of bodies and allocates all allocatable arrays procedure :: accel_user => user_kick_getacch_body !! Add user-supplied heliocentric accelerations to planets - procedure :: copy => util_copy_body !! Copies elements from one structure to another + procedure :: append => util_append_body !! Appends elements from one structure to another + procedure :: copy_into => util_copy_into_body !! Copies elements from one Swiftest body object to another. procedure :: fill => util_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) procedure :: resize => 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 => util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) @@ -735,6 +736,14 @@ module subroutine user_kick_getacch_body(self, system, param, t, lbeg) logical, intent(in) :: lbeg !! Optional argument that determines whether or not this is the beginning or end of the step end subroutine user_kick_getacch_body + module subroutine util_append_body(self, source, param, lmask) + implicit none + class(swiftest_body), intent(inout) :: self !! Swiftest body object + class(swiftest_body), intent(in) :: source !! Source object to append + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + logical, dimension(:), optional, intent(in) :: lmask !! Logical mask indicating which elements to append to + end subroutine util_append_body + module subroutine util_coord_b2h_pl(self, cb) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object @@ -759,12 +768,13 @@ module subroutine util_coord_h2b_tp(self, cb) class(swiftest_cb), intent(in) :: cb !! Swiftest central body object end subroutine util_coord_h2b_tp - module subroutine util_copy_body(self, source, param) + module subroutine util_copy_into_body(self, source, param, lmask) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(in) :: source !! Source object to copy - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - end subroutine util_copy_body + class(swiftest_body), intent(inout) :: self !! Swiftest body object + class(swiftest_body), intent(in) :: source !! Source object to append + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + logical, dimension(:), optional, intent(in) :: lmask !! Logical mask indicating which elements to append to + end subroutine util_copy_into_body module subroutine util_exit(code) implicit none diff --git a/src/util/util_append.f90 b/src/util/util_append.f90 new file mode 100644 index 000000000..3541ed8e3 --- /dev/null +++ b/src/util/util_append.f90 @@ -0,0 +1,24 @@ +submodule (swiftest_classes) s_util_append + use swiftest +contains + + module subroutine util_append_body(self, source, param, lmask) + !! author: David A. Minton + !! + !! Append components from one Swiftest body object to another. + !! This method will automatically resize the destination body if it is too small + implicit none + ! Arguments + class(swiftest_body), intent(inout) :: self !! Swiftest body object + class(swiftest_body), intent(in) :: source !! Source object to append + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + logical, dimension(:), optional, intent(in) :: lmask !! Logical mask indicating which elements to append to + + associate(nold => self%nbody, nnew => source%nbody) + if (nnew > size(self%status)) call self%resize(nnew, param) + + end associate + return + end subroutine util_append_body + +end submodule s_util_append \ No newline at end of file diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 index fcbd0d5da..4d85e7f0c 100644 --- a/src/util/util_copy.f90 +++ b/src/util/util_copy.f90 @@ -2,18 +2,30 @@ use swiftest contains - module subroutine util_copy_body(self, source, param) + module subroutine util_copy_into_body(self, source, param, lmask) !! author: David A. Minton !! - !! Non-destructively copy components from one Swiftest body object to another. + !! Copies elements from one Swiftest body object to another. !! This method will automatically resize the destination body if it is too small implicit none ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(in) :: source !! Source object to copy - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self !! Swiftest body object + class(swiftest_body), intent(in) :: source !! Source object to append + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + logical, dimension(:), optional, intent(in) :: lmask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B) :: nnew + if (present(lmask)) then + nnew = count(lmask) + else + nnew = size(source%status) + end if + associate(nold => self%nbody) + if (nnew > size(self%status)) call self%resize(nnew, param) + + end associate return - end subroutine util_copy_body + end subroutine util_copy_into_body end submodule s_util_copy \ No newline at end of file diff --git a/src/util/util_resize.f90 b/src/util/util_resize.f90 index cde0428d4..986053546 100644 --- a/src/util/util_resize.f90 +++ b/src/util/util_resize.f90 @@ -26,7 +26,7 @@ module subroutine util_resize_body(self, nrequested, param) if (lmalloc) allocate(temp, source=self) call self%setup(nrequested, param) if (lmalloc) then - call self%copy(temp, param) + call self%copy_into(temp, param) deallocate(temp) end if else From 8cd8464eb9ca20104b66062938d2a41902571185 Mon Sep 17 00:00:00 2001 From: David Minton Date: Sat, 31 Jul 2021 10:28:35 -0400 Subject: [PATCH 03/42] Refactored fill and spill routines into copy submodule and added a specialized copy method that uses a fill operation --- src/modules/rmvs_classes.f90 | 30 +- src/modules/swiftest_classes.f90 | 56 ++-- src/modules/whm_classes.f90 | 18 +- src/rmvs/rmvs_util.f90 | 28 +- src/util/util_append.f90 | 4 +- src/util/util_copy.f90 | 512 ++++++++++++++++++++++++++++++- src/util/util_spill_and_fill.f90 | 506 ------------------------------ src/whm/whm_util.f90 | 14 +- 8 files changed, 581 insertions(+), 587 deletions(-) delete mode 100644 src/util/util_spill_and_fill.f90 diff --git a/src/modules/rmvs_classes.f90 b/src/modules/rmvs_classes.f90 index 88e3ee217..945b96ce2 100644 --- a/src/modules/rmvs_classes.f90 +++ b/src/modules/rmvs_classes.f90 @@ -53,7 +53,7 @@ module rmvs_classes !! RMVS test particle class type, extends(whm_tp) :: rmvs_tp !! Note to developers: If you add componenets to this class, be sure to update methods and subroutines that traverse the - !! component list, such as rmvs_setup_tp and rmvs_util_spill_tp + !! component list, such as rmvs_setup_tp and rmvs_util_copy_spill_tp ! encounter steps) logical, dimension(:), allocatable :: lperi !! planetocentric pericenter passage flag (persistent for a full rmvs time step) over a full RMVS time step) integer(I4B), dimension(:), allocatable :: plperP !! index of planet associated with pericenter distance peri (persistent over a full RMVS time step) @@ -71,10 +71,10 @@ module rmvs_classes procedure :: accel => rmvs_kick_getacch_tp !! Calculates either the standard or modified version of the acceleration depending if the !! if the test particle is undergoing a close encounter or not procedure :: setup => rmvs_setup_tp !! Constructor method - Allocates space for number of particles - procedure :: fill => rmvs_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => rmvs_util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) procedure :: sort => rmvs_util_sort_tp !! Sorts body arrays by a sortable componen procedure :: rearrange => rmvs_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => rmvs_util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => rmvs_util_copy_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type rmvs_tp !******************************************************************************************************************************** @@ -94,8 +94,8 @@ module rmvs_classes procedure :: setup => rmvs_setup_pl !! Constructor method - Allocates space for number of particles procedure :: sort => rmvs_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => rmvs_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: fill => rmvs_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) - procedure :: spill => rmvs_util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: fill => rmvs_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: spill => rmvs_util_copy_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type rmvs_pl interface @@ -154,21 +154,21 @@ module subroutine rmvs_setup_tp(self, n, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parametere end subroutine rmvs_setup_tp - module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) + module subroutine rmvs_util_copy_fill_pl(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none class(rmvs_pl), intent(inout) :: self !! RMVS massive body object - class(swiftest_body), intent(inout) :: inserts !! Inserted object + class(swiftest_body), intent(in) :: inserts !! Inserted object logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps - end subroutine rmvs_util_fill_pl + end subroutine rmvs_util_copy_fill_pl - module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) + module subroutine rmvs_util_copy_fill_tp(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none class(rmvs_tp), intent(inout) :: self !! RMVS massive body object - class(swiftest_body), intent(inout) :: inserts !! Inserted object + class(swiftest_body), intent(in) :: inserts !! Inserted object logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps - end subroutine rmvs_util_fill_tp + end subroutine rmvs_util_copy_fill_tp module subroutine rmvs_util_sort_pl(self, sortby, ascending) implicit none @@ -196,21 +196,21 @@ module subroutine rmvs_util_sort_rearrange_tp(self, ind) 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 rmvs_util_sort_rearrange_tp - module subroutine rmvs_util_spill_pl(self, discards, lspill_list) + module subroutine rmvs_util_copy_spill_pl(self, discards, lspill_list) use swiftest_classes, only : swiftest_body implicit none class(rmvs_pl), intent(inout) :: self !! RMVS 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 - end subroutine rmvs_util_spill_pl + end subroutine rmvs_util_copy_spill_pl - module subroutine rmvs_util_spill_tp(self, discards, lspill_list) + module subroutine rmvs_util_copy_spill_tp(self, discards, lspill_list) use swiftest_classes, only : swiftest_body implicit none class(rmvs_tp), intent(inout) :: self !! RMVS 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 - end subroutine rmvs_util_spill_tp + end subroutine rmvs_util_copy_spill_tp module subroutine rmvs_step_system(self, param, t, dt) use swiftest_classes, only : swiftest_parameters diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index ac7639bc4..5ec4fc7dc 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -145,7 +145,7 @@ module swiftest_classes real(DP), dimension(:), allocatable :: mu !! G * (Mcb + [m]) logical, dimension(:), allocatable :: lmask !! Logical mask used to select a subset of bodies when performing certain operations (drift, kick, accel, etc.) !! 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 + !! component list, such as setup_body and util_copy_spill contains procedure(abstract_discard_body), deferred :: discard procedure(abstract_kick_body), deferred :: kick @@ -166,12 +166,12 @@ module swiftest_classes procedure :: accel_user => user_kick_getacch_body !! Add user-supplied heliocentric accelerations to planets procedure :: append => util_append_body !! Appends elements from one structure to another procedure :: copy_into => util_copy_into_body !! Copies elements from one Swiftest body object to another. - procedure :: fill => util_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => util_copy_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) procedure :: resize => 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 => util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) procedure :: sort => util_sort_body !! Sorts body arrays by a sortable componen procedure :: rearrange => util_sort_rearrange_body !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => util_spill_body !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => util_copy_spill_body !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type swiftest_body !******************************************************************************************************************************** @@ -196,7 +196,7 @@ module swiftest_classes 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 !! 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 + !! component list, such as setup_pl and util_copy_spill_pl contains ! Massive body-specific concrete methods ! These are concrete because they are the same implemenation for all integrators @@ -208,13 +208,13 @@ module swiftest_classes procedure :: accel_tides => tides_kick_getacch_pl !! Compute the accelerations of bodies due to tidal interactions with the central body procedure :: h2b => util_coord_h2b_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) procedure :: b2h => util_coord_b2h_pl !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) - procedure :: fill => util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) procedure :: set_beg_end => util_set_beg_end_pl !! Sets the beginning and ending positions and velocities of planets. procedure :: set_mu => util_set_mu_pl !! Method used to construct the vectorized form of the central body mass procedure :: set_rhill => util_set_rhill !! Calculates the Hill's radii for each body procedure :: sort => util_sort_pl !! Sorts body arrays by a sortable component procedure :: rearrange => util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => util_copy_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type swiftest_pl !******************************************************************************************************************************** @@ -227,7 +227,7 @@ module swiftest_classes real(DP), dimension(:), allocatable :: peri !! Perihelion distance real(DP), dimension(:), allocatable :: atp !! Semimajor axis following perihelion passage !! 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_tp and util_spill_tp + !! component list, such as setup_tp and util_copy_spill_tp contains ! Test particle-specific concrete methods ! These are concrete because they are the same implemenation for all integrators @@ -237,12 +237,12 @@ module swiftest_classes procedure :: setup => setup_tp !! A base constructor that sets the number of bodies and procedure :: h2b => util_coord_h2b_tp !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) procedure :: b2h => util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) - procedure :: fill => util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) procedure :: get_peri => util_peri_tp !! Determine system pericenter passages for test particles procedure :: set_mu => util_set_mu_tp !! Method used to construct the vectorized form of the central body mass procedure :: sort => util_sort_tp !! Sorts body arrays by a sortable component procedure :: rearrange => util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => util_copy_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type swiftest_tp !******************************************************************************************************************************** @@ -736,12 +736,12 @@ module subroutine user_kick_getacch_body(self, system, param, t, lbeg) logical, intent(in) :: lbeg !! Optional argument that determines whether or not this is the beginning or end of the step end subroutine user_kick_getacch_body - module subroutine util_append_body(self, source, param, lmask) + module subroutine util_append_body(self, source, param, lsource_mask) implicit none class(swiftest_body), intent(inout) :: self !! Swiftest body object class(swiftest_body), intent(in) :: source !! Source object to append class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - logical, dimension(:), optional, intent(in) :: lmask !! Logical mask indicating which elements to append to + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_append_body module subroutine util_coord_b2h_pl(self, cb) @@ -768,12 +768,12 @@ module subroutine util_coord_h2b_tp(self, cb) class(swiftest_cb), intent(in) :: cb !! Swiftest central body object end subroutine util_coord_h2b_tp - module subroutine util_copy_into_body(self, source, param, lmask) + module subroutine util_copy_into_body(self, source, param, lsource_mask) implicit none class(swiftest_body), intent(inout) :: self !! Swiftest body object class(swiftest_body), intent(in) :: source !! Source object to append class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - logical, dimension(:), optional, intent(in) :: lmask !! Logical mask indicating which elements to append to + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_copy_into_body module subroutine util_exit(code) @@ -781,26 +781,26 @@ module subroutine util_exit(code) integer(I4B), intent(in) :: code !! Failure exit code end subroutine util_exit - module subroutine util_fill_body(self, inserts, lfill_list) + module subroutine util_copy_fill_body(self, inserts, lfill_list) implicit none class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(inout) :: inserts !! Swiftest body object to be inserted + 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 util_fill_body + end subroutine util_copy_fill_body - module subroutine util_fill_pl(self, inserts, lfill_list) + module subroutine util_copy_fill_pl(self, inserts, lfill_list) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_body), intent(inout) :: inserts !! Swiftest body object to be inserted + 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 util_fill_pl + end subroutine util_copy_fill_pl - module subroutine util_fill_tp(self, inserts, lfill_list) + module subroutine util_copy_fill_tp(self, inserts, lfill_list) implicit none class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_body), intent(inout) :: inserts !! Swiftest body object to be inserted + 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 util_fill_tp + end subroutine util_copy_fill_tp module subroutine util_peri_tp(self, system, param) implicit none @@ -934,26 +934,26 @@ module subroutine util_sort_tp(self, sortby, ascending) 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) + module subroutine util_copy_spill_body(self, discards, lspill_list) 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 - end subroutine util_spill_body + end subroutine util_copy_spill_body - module subroutine util_spill_pl(self, discards, lspill_list) + module subroutine util_copy_spill_pl(self, discards, lspill_list) 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 - end subroutine util_spill_pl + end subroutine util_copy_spill_pl - module subroutine util_spill_tp(self, discards, lspill_list) + module subroutine util_copy_spill_tp(self, discards, lspill_list) 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 - end subroutine util_spill_tp + end subroutine util_copy_spill_tp module subroutine util_valid(pl, tp) implicit none diff --git a/src/modules/whm_classes.f90 b/src/modules/whm_classes.f90 index 5509a3afe..d64354c08 100644 --- a/src/modules/whm_classes.f90 +++ b/src/modules/whm_classes.f90 @@ -28,13 +28,13 @@ module whm_classes real(DP), dimension(:), allocatable :: muj !! Jacobi mu: GMcb * eta(i) / eta(i - 1) real(DP), dimension(:), allocatable :: ir3j !! Third term of heliocentric acceleration !! Note to developers: If you add componenets to this class, be sure to update methods and subroutines that traverse the - !! component list, such as whm_setup_pl and whm_util_spill_pl + !! component list, such as whm_setup_pl and whm_util_copy_spill_pl contains procedure :: h2j => whm_coord_h2j_pl !! Convert position and velcoity vectors from heliocentric to Jacobi coordinates procedure :: j2h => whm_coord_j2h_pl !! Convert position and velcoity vectors from Jacobi to helliocentric coordinates procedure :: vh2vj => whm_coord_vh2vj_pl !! Convert velocity vectors from heliocentric to Jacobi coordinates procedure :: drift => whm_drift_pl !! Loop through massive bodies and call Danby drift routine to jacobi coordinates - procedure :: fill => whm_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => whm_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) procedure :: accel => whm_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies procedure :: kick => whm_kick_vh_pl !! Kick heliocentric velocities of massive bodies procedure :: accel_gr => whm_gr_kick_getacch_pl !! Acceleration term arising from the post-Newtonian correction @@ -45,7 +45,7 @@ module whm_classes procedure :: sort => whm_util_sort_pl !! Sort a WHM massive body object in-place. procedure :: rearrange => whm_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods procedure :: step => whm_step_pl !! Steps the body forward one stepsize - procedure :: spill => whm_util_spill_pl !!"Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => whm_util_copy_spill_pl !!"Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type whm_pl !******************************************************************************************************************************** @@ -55,7 +55,7 @@ module whm_classes !! WHM test particle class type, extends(swiftest_tp) :: whm_tp !! Note to developers: If you add componenets to this class, be sure to update methods and subroutines that traverse the - !! component list, such as whm_util_spill_tp + !! component list, such as whm_util_copy_spill_tp contains procedure :: accel => whm_kick_getacch_tp !! Compute heliocentric accelerations of test particles procedure :: kick => whm_kick_vh_tp !! Kick heliocentric velocities of test particles @@ -106,13 +106,13 @@ module subroutine whm_drift_pl(self, system, param, dt) real(DP), intent(in) :: dt !! Stepsize end subroutine whm_drift_pl - module subroutine whm_util_fill_pl(self, inserts, lfill_list) + module subroutine whm_util_copy_fill_pl(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none class(whm_pl), intent(inout) :: self !! WHM massive body object - class(swiftest_body), intent(inout) :: inserts !! inserted object + class(swiftest_body), intent(in) :: inserts !! inserted object logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps - end subroutine whm_util_fill_pl + end subroutine whm_util_copy_fill_pl !> Get heliocentric accelration of massive bodies module subroutine whm_kick_getacch_pl(self, system, param, t, lbeg) @@ -249,13 +249,13 @@ module subroutine whm_step_tp(self, system, param, t, dt) real(DP), intent(in) :: dt !! Stepsize end subroutine whm_step_tp - module subroutine whm_util_spill_pl(self, discards, lspill_list) + module subroutine whm_util_copy_spill_pl(self, discards, lspill_list) use swiftest_classes, only : swiftest_body implicit none class(whm_pl), intent(inout) :: self !! WHM 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 - end subroutine whm_util_spill_pl + end subroutine whm_util_copy_spill_pl !> Steps the Swiftest nbody system forward in time one stepsize module subroutine whm_step_system(self, param, t, dt) diff --git a/src/rmvs/rmvs_util.f90 b/src/rmvs/rmvs_util.f90 index 27b6bd4b3..863033c17 100644 --- a/src/rmvs/rmvs_util.f90 +++ b/src/rmvs/rmvs_util.f90 @@ -2,7 +2,7 @@ use swiftest contains - module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) + module subroutine rmvs_util_copy_fill_pl(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new RMVS massive body structure into an old one. @@ -11,7 +11,7 @@ module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) implicit none ! Arguments class(rmvs_pl), intent(inout) :: self !! RMVS massive body object - class(swiftest_body), intent(inout) :: inserts !! Inserted object + class(swiftest_body), intent(in) :: inserts !! Inserted object logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps ! Internals integer(I4B) :: i @@ -23,17 +23,17 @@ module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) keeps%nenc(:) = unpack(keeps%nenc(:), .not.lfill_list(:), keeps%nenc(:)) keeps%nenc(:) = unpack(inserts%nenc(:), lfill_list(:), keeps%nenc(:)) - call whm_util_fill_pl(keeps, inserts, lfill_list) + call whm_util_copy_fill_pl(keeps, inserts, lfill_list) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' end select end associate return - end subroutine rmvs_util_fill_pl + end subroutine rmvs_util_copy_fill_pl - module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) + module subroutine rmvs_util_copy_fill_tp(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new RMVS test particle structure into an old one. @@ -42,7 +42,7 @@ module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) implicit none ! Arguments class(rmvs_tp), intent(inout) :: self !! RMVS test particle object - class(swiftest_body), intent(inout) :: inserts !! Inserted 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) @@ -58,14 +58,14 @@ module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) keeps%plencP(:) = unpack(keeps%plencP(:), .not.lfill_list(:), keeps%plencP(:)) keeps%plencP(:) = unpack(inserts%plencP(:), lfill_list(:), keeps%plencP(:)) - call util_fill_tp(keeps, inserts, lfill_list) + call util_copy_fill_tp(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on rmvs_tp' end select end associate return - end subroutine rmvs_util_fill_tp + end subroutine rmvs_util_copy_fill_tp module subroutine rmvs_util_sort_pl(self, sortby, ascending) !! author: David A. Minton @@ -206,7 +206,7 @@ module subroutine rmvs_util_sort_rearrange_tp(self, ind) end subroutine rmvs_util_sort_rearrange_tp - module subroutine rmvs_util_spill_pl(self, discards, lspill_list) + module subroutine rmvs_util_copy_spill_pl(self, discards, lspill_list) !! author: David A. Minton !! !! Move spilled (discarded) RMVS test particle structure from active list to discard list @@ -227,17 +227,17 @@ module subroutine rmvs_util_spill_pl(self, discards, lspill_list) if (count(.not.lspill_list(:)) > 0) then keeps%nenc(:) = pack(keeps%nenc(:), .not. lspill_list(:)) end if - call whm_util_spill_pl(keeps, discards, lspill_list) + call whm_util_copy_spill_pl(keeps, discards, lspill_list) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' end select end associate return - end subroutine rmvs_util_spill_pl + end subroutine rmvs_util_copy_spill_pl - module subroutine rmvs_util_spill_tp(self, discards, lspill_list) + module subroutine rmvs_util_copy_spill_tp(self, discards, lspill_list) !! author: David A. Minton !! !! Move spilled (discarded) RMVS test particle structure from active list to discard list @@ -263,13 +263,13 @@ module subroutine rmvs_util_spill_tp(self, discards, lspill_list) keeps%plencP(:) = pack(keeps%plencP(:), .not. lspill_list(:)) end if - call util_spill_tp(keeps, discards, lspill_list) + call util_copy_spill_tp(keeps, discards, lspill_list) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_tp' end select end associate return - end subroutine rmvs_util_spill_tp + end subroutine rmvs_util_copy_spill_tp end submodule s_rmvs_util diff --git a/src/util/util_append.f90 b/src/util/util_append.f90 index 3541ed8e3..3a5b3ba81 100644 --- a/src/util/util_append.f90 +++ b/src/util/util_append.f90 @@ -2,7 +2,7 @@ use swiftest contains - module subroutine util_append_body(self, source, param, lmask) + module subroutine util_append_body(self, source, param, lsource_mask) !! author: David A. Minton !! !! Append components from one Swiftest body object to another. @@ -12,7 +12,7 @@ module subroutine util_append_body(self, source, param, lmask) class(swiftest_body), intent(inout) :: self !! Swiftest body object class(swiftest_body), intent(in) :: source !! Source object to append class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - logical, dimension(:), optional, intent(in) :: lmask !! Logical mask indicating which elements to append to + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to associate(nold => self%nbody, nnew => source%nbody) if (nnew > size(self%status)) call self%resize(nnew, param) diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 index 4d85e7f0c..ad3c111c4 100644 --- a/src/util/util_copy.f90 +++ b/src/util/util_copy.f90 @@ -2,7 +2,250 @@ use swiftest contains - module subroutine util_copy_into_body(self, source, param, lmask) + module subroutine util_copy_fill_body(self, inserts, lfill_list) + !! author: David A. Minton + !! + !! Insert new Swiftest generic particle structure into an old one. + !! This is the inverse of a fill operation. + implicit none + ! Arguments + class(swiftest_body), intent(inout) :: self !! Swiftest generic 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 + ! internals + integer(I4B) :: i + + ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps + !> Spill all the common components + associate(keeps => self) + keeps%id(:) = unpack(keeps%id(:), .not.lfill_list(:), keeps%id(:)) + keeps%id(:) = unpack(inserts%id(:), lfill_list(:), keeps%id(:)) + + keeps%name(:) = unpack(keeps%name(:), .not.lfill_list(:), keeps%name(:)) + keeps%name(:) = unpack(inserts%name(:), lfill_list(:), keeps%name(:)) + + keeps%status(:) = unpack(keeps%status(:), .not.lfill_list(:), keeps%status(:)) + keeps%status(:) = unpack(inserts%status(:), lfill_list(:), keeps%status(:)) + + keeps%ldiscard(:) = unpack(keeps%ldiscard(:), .not.lfill_list(:), keeps%ldiscard(:)) + keeps%ldiscard(:) = unpack(inserts%ldiscard(:), lfill_list(:), keeps%ldiscard(:)) + + keeps%mu(:) = unpack(keeps%mu(:), .not.lfill_list(:), keeps%mu(:)) + keeps%mu(:) = unpack(inserts%mu(:), lfill_list(:), keeps%mu(:)) + + keeps%lmask(:) = unpack(keeps%lmask(:), .not.lfill_list(:), keeps%ldiscard(:)) + keeps%lmask(:) = unpack(inserts%lmask(:), lfill_list(:), keeps%ldiscard(:)) + + do i = 1, NDIM + keeps%xh(i, :) = unpack(keeps%xh(i, :), .not.lfill_list(:), keeps%xh(i, :)) + keeps%xh(i, :) = unpack(inserts%xh(i, :), lfill_list(:), keeps%xh(i, :)) + + keeps%vh(i, :) = unpack(keeps%vh(i, :), .not.lfill_list(:), keeps%vh(i, :)) + keeps%vh(i, :) = unpack(inserts%vh(i, :), lfill_list(:), keeps%vh(i, :)) + + keeps%xb(i, :) = unpack(keeps%xb(i, :), .not.lfill_list(:), keeps%xb(i, :)) + keeps%xb(i, :) = unpack(inserts%xb(i, :), lfill_list(:), keeps%xb(i, :)) + + keeps%vb(i, :) = unpack(keeps%vb(i, :), .not.lfill_list(:), keeps%vb(i, :)) + keeps%vb(i, :) = unpack(inserts%vb(i, :), lfill_list(:), keeps%vb(i, :)) + + keeps%ah(i, :) = unpack(keeps%ah(i, :), .not.lfill_list(:), keeps%ah(i, :)) + keeps%ah(i, :) = unpack(inserts%ah(i, :), lfill_list(:), keeps%ah(i, :)) + end do + + if (allocated(keeps%aobl)) then + do i = 1, NDIM + keeps%aobl(i, :) = unpack(keeps%aobl(i, :), .not.lfill_list(:), keeps%aobl(i, :)) + keeps%aobl(i, :) = unpack(inserts%aobl(i, :), lfill_list(:), keeps%aobl(i, :)) + end do + end if + + if (allocated(keeps%agr)) then + do i = 1, NDIM + keeps%agr(i, :) = unpack(keeps%agr(i, :), .not.lfill_list(:), keeps%agr(i, :)) + keeps%agr(i, :) = unpack(inserts%agr(i, :), lfill_list(:), keeps%agr(i, :)) + end do + end if + + if (allocated(keeps%atide)) then + do i = 1, NDIM + keeps%atide(i, :) = unpack(keeps%atide(i, :), .not.lfill_list(:), keeps%atide(i, :)) + keeps%atide(i, :) = unpack(inserts%atide(i, :), lfill_list(:), keeps%atide(i, :)) + end do + end if + + if (allocated(keeps%a)) then + keeps%a(:) = unpack(keeps%a(:), .not.lfill_list(:), keeps%a(:)) + keeps%a(:) = unpack(inserts%a(:), lfill_list(:), keeps%a(:)) + end if + + if (allocated(keeps%e)) then + keeps%e(:) = unpack(keeps%e(:), .not.lfill_list(:), keeps%e(:)) + keeps%e(:) = unpack(inserts%e(:), lfill_list(:), keeps%e(:)) + end if + + if (allocated(keeps%inc)) then + keeps%inc(:) = unpack(keeps%inc(:), .not.lfill_list(:), keeps%inc(:)) + keeps%inc(:) = unpack(inserts%inc(:), lfill_list(:), keeps%inc(:)) + end if + + if (allocated(keeps%capom)) then + keeps%capom(:) = unpack(keeps%capom(:),.not.lfill_list(:), keeps%capom(:)) + keeps%capom(:) = unpack(inserts%capom(:),lfill_list(:), keeps%capom(:)) + end if + + if (allocated(keeps%omega)) then + keeps%omega(:) = unpack(keeps%omega(:),.not.lfill_list(:), keeps%omega(:)) + keeps%omega(:) = unpack(inserts%omega(:),lfill_list(:), keeps%omega(:)) + end if + + if (allocated(keeps%capm)) then + keeps%capm(:) = unpack(keeps%capm(:), .not.lfill_list(:), keeps%capm(:)) + keeps%capm(:) = unpack(inserts%capm(:), lfill_list(:), keeps%capm(:)) + end if + + ! This is the base class, so will be the last to be called in the cascade. + keeps%nbody = size(keeps%id(:)) + end associate + + return + end subroutine util_copy_fill_body + + + module subroutine util_copy_fill_pl(self, inserts, lfill_list) + !! author: David A. Minton + !! + !! Insert new Swiftest massive body structure into an old one. + !! This is the inverse of a fill operation. + implicit none + ! Arguments + 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 + ! Internals + integer(I4B) :: i + + associate(keeps => self) + + select type (inserts) ! The standard requires us to select the type of both arguments in order to access all the components + class is (swiftest_pl) + !> Spill components specific to the massive body class + keeps%mass(:) = unpack(keeps%mass(:),.not.lfill_list(:), keeps%mass(:)) + keeps%mass(:) = unpack(inserts%mass(:),lfill_list(:), keeps%mass(:)) + + keeps%Gmass(:) = unpack(keeps%Gmass(:),.not.lfill_list(:), keeps%Gmass(:)) + keeps%Gmass(:) = unpack(inserts%Gmass(:),lfill_list(:), keeps%Gmass(:)) + + keeps%rhill(:) = unpack(keeps%rhill(:),.not.lfill_list(:), keeps%rhill(:)) + keeps%rhill(:) = unpack(inserts%rhill(:),lfill_list(:), keeps%rhill(:)) + + if (allocated(keeps%radius) .and. allocated(inserts%radius)) then + keeps%radius(:) = unpack(keeps%radius(:),.not.lfill_list(:), keeps%radius(:)) + keeps%radius(:) = unpack(inserts%radius(:),lfill_list(:), keeps%radius(:)) + end if + + if (allocated(keeps%density) .and. allocated(inserts%density)) then + keeps%density(:) = unpack(keeps%density(:),.not.lfill_list(:), keeps%density(:)) + keeps%density(:) = unpack(inserts%density(:),lfill_list(:), keeps%density(:)) + end if + + if (allocated(keeps%k2) .and. allocated(inserts%k2)) then + keeps%k2(:) = unpack(keeps%k2(:),.not.lfill_list(:), keeps%k2(:)) + keeps%k2(:) = unpack(inserts%k2(:),lfill_list(:), keeps%k2(:)) + end if + + if (allocated(keeps%Q) .and. allocated(inserts%Q)) then + keeps%Q(:) = unpack(keeps%Q(:),.not.lfill_list(:), keeps%Q(:)) + keeps%Q(:) = unpack(inserts%Q(:),lfill_list(:), keeps%Q(:)) + end if + + if (allocated(keeps%tlag) .and. allocated(inserts%tlag)) then + keeps%tlag(:) = unpack(keeps%tlag(:),.not.lfill_list(:), keeps%tlag(:)) + keeps%tlag(:) = unpack(inserts%tlag(:),lfill_list(:), keeps%tlag(:)) + end if + + if (allocated(keeps%xbeg) .and. allocated(inserts%xbeg)) then + do i = 1, NDIM + keeps%xbeg(i, :) = unpack(keeps%xbeg(i, :), .not.lfill_list(:), keeps%xbeg(i, :)) + keeps%xbeg(i, :) = unpack(inserts%xbeg(i, :), lfill_list(:), keeps%xbeg(i, :)) + end do + end if + + if (allocated(keeps%xend) .and. allocated(inserts%xend)) then + do i = 1, NDIM + keeps%xend(i, :) = unpack(keeps%xend(i, :), .not.lfill_list(:), keeps%xend(i, :)) + keeps%xend(i, :) = unpack(inserts%xend(i, :), lfill_list(:), keeps%xend(i, :)) + end do + end if + + if (allocated(keeps%vbeg) .and. allocated(inserts%vbeg)) then + do i = 1, NDIM + keeps%vbeg(i, :) = unpack(keeps%vbeg(i, :), .not.lfill_list(:), keeps%vbeg(i, :)) + keeps%vbeg(i, :) = unpack(inserts%vbeg(i, :), lfill_list(:), keeps%vbeg(i, :)) + end do + end if + + if (allocated(keeps%Ip) .and. allocated(inserts%Ip)) then + do i = 1, NDIM + keeps%Ip(i, :) = unpack(keeps%Ip(i, :), .not.lfill_list(:), keeps%Ip(i, :)) + keeps%Ip(i, :) = unpack(inserts%Ip(i, :), lfill_list(:), keeps%Ip(i, :)) + end do + end if + + if (allocated(keeps%rot) .and. allocated(inserts%rot)) then + do i = 1, NDIM + keeps%rot(i, :) = unpack(keeps%rot(i, :), .not.lfill_list(:), keeps%rot(i, :)) + keeps%rot(i, :) = unpack(inserts%rot(i, :), lfill_list(:), keeps%rot(i, :)) + end do + end if + + keeps%ldiscard(:) = unpack(inserts%ldiscard(:), lfill_list(:), keeps%ldiscard(:)) + + call util_copy_fill_body(keeps, inserts, lfill_list) + class default + write(*,*) 'Error! fill method called for incompatible return type on swiftest_pl' + end select + end associate + + return + end subroutine util_copy_fill_pl + + + module subroutine util_copy_fill_tp(self, inserts, lfill_list) + !! author: David A. Minton + !! + !! Insert new Swiftest test particle structure into an old one. + !! This is the inverse of a fill operation. + implicit none + ! Arguments + 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 + + associate(keeps => self) + select type(inserts) + class is (swiftest_tp) + !> Spill components specific to the test particle class + keeps%isperi(:) = unpack(keeps%isperi(:), .not.lfill_list(:), keeps%isperi(:)) + keeps%isperi(:) = unpack(inserts%isperi(:), lfill_list(:), keeps%isperi(:)) + + keeps%peri(:) = unpack(keeps%peri(:), .not.lfill_list(:), keeps%peri(:)) + keeps%peri(:) = unpack(inserts%peri(:), lfill_list(:), keeps%peri(:)) + + keeps%atp(:) = unpack(keeps%atp(:), .not.lfill_list(:), keeps%atp(:)) + keeps%atp(:) = unpack(inserts%atp(:), lfill_list(:), keeps%atp(:)) + + call util_copy_fill_body(keeps, inserts, lfill_list) + class default + write(*,*) 'Error! fill method called for incompatible return type on swiftest_tp' + end select + end associate + + return + end subroutine util_copy_fill_tp + + + module subroutine util_copy_into_body(self, source, param, lsource_mask) !! author: David A. Minton !! !! Copies elements from one Swiftest body object to another. @@ -12,20 +255,277 @@ module subroutine util_copy_into_body(self, source, param, lmask) class(swiftest_body), intent(inout) :: self !! Swiftest body object class(swiftest_body), intent(in) :: source !! Source object to append class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - logical, dimension(:), optional, intent(in) :: lmask !! Logical mask indicating which elements to append to + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to ! Internals - integer(I4B) :: nnew + integer(I4B) :: i,nnew + logical, dimension(:), allocatable :: lfill_list - if (present(lmask)) then - nnew = count(lmask) + if (present(lsource_mask)) then + nnew = count(lsource_mask) else nnew = size(source%status) end if + allocate(lfill_list(size(self%status))) + lfill_list = .false. + lfill_list(1:nnew) = .true. associate(nold => self%nbody) if (nnew > size(self%status)) call self%resize(nnew, param) - + call self%fill(source, lfill_list) end associate return end subroutine util_copy_into_body + + module subroutine util_copy_spill_body(self, discards, lspill_list) + !! author: David A. Minton + !! + !! Move spilled (discarded) Swiftest generic particle structure from active list to discard list + !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 + implicit none + ! Arguments + class(swiftest_body), intent(inout) :: self !! Swiftest generic 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 + ! Internals + integer(I4B) :: i + + ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps + !> Spill all the common components + associate(keeps => self) + discards%id(:) = pack(keeps%id(:), lspill_list(:)) + discards%name(:) = pack(keeps%name(:), lspill_list(:)) + discards%status(:) = pack(keeps%status(:), lspill_list(:)) + discards%mu(:) = pack(keeps%mu(:), lspill_list(:)) + discards%lmask(:) = pack(keeps%lmask(:), lspill_list(:)) + do i = 1, NDIM + discards%xh(i, :) = pack(keeps%xh(i, :), lspill_list(:)) + discards%vh(i, :) = pack(keeps%vh(i, :), lspill_list(:)) + discards%xb(i, :) = pack(keeps%xb(i, :), lspill_list(:)) + discards%vb(i, :) = pack(keeps%vb(i, :), lspill_list(:)) + discards%ah(i, :) = pack(keeps%ah(i, :), lspill_list(:)) + end do + + if (allocated(keeps%a)) discards%a(:) = pack(keeps%a(:), lspill_list(:)) + if (allocated(keeps%e)) discards%e(:) = pack(keeps%e(:), lspill_list(:)) + if (allocated(keeps%capom)) discards%capom(:) = pack(keeps%capom(:), lspill_list(:)) + if (allocated(keeps%omega)) discards%omega(:) = pack(keeps%omega(:), lspill_list(:)) + if (allocated(keeps%capm)) discards%capm(:) = pack(keeps%capm(:), lspill_list(:)) + + + if (allocated(keeps%aobl)) then + do i = 1, NDIM + discards%aobl(i, :) = pack(keeps%aobl(i, :), lspill_list(:)) + end do + end if + if (allocated(keeps%agr)) then + do i = 1, NDIM + discards%agr(i, :) = pack(keeps%agr(i, :), lspill_list(:)) + end do + end if + if (allocated(keeps%atide)) then + do i = 1, NDIM + discards%atide(i, :) = pack(keeps%atide(i, :), lspill_list(:)) + end do + end if + + if (count(.not.lspill_list(:)) > 0) then + keeps%id(:) = pack(keeps%id(:), .not. lspill_list(:)) + keeps%name(:) = pack(keeps%name(:), .not. lspill_list(:)) + keeps%status(:) = pack(keeps%status(:), .not. lspill_list(:)) + keeps%mu(:) = pack(keeps%mu(:), .not. lspill_list(:)) + keeps%lmask(:) = pack(keeps%lmask(:), .not. lspill_list(:)) + + do i = 1, NDIM + keeps%xh(i, :) = pack(keeps%xh(i, :), .not. lspill_list(:)) + keeps%vh(i, :) = pack(keeps%vh(i, :), .not. lspill_list(:)) + keeps%xb(i, :) = pack(keeps%xb(i, :), .not. lspill_list(:)) + keeps%vb(i, :) = pack(keeps%vb(i, :), .not. lspill_list(:)) + keeps%ah(i, :) = pack(keeps%ah(i, :), .not. lspill_list(:)) + end do + + if (allocated(keeps%a)) keeps%a(:) = pack(keeps%a(:), .not. lspill_list(:)) + if (allocated(keeps%e)) keeps%e(:) = pack(keeps%e(:), .not. lspill_list(:)) + if (allocated(keeps%inc)) keeps%inc(:) = pack(keeps%inc(:), .not. lspill_list(:)) + if (allocated(keeps%capom)) keeps%capom(:) = pack(keeps%capom(:), .not. lspill_list(:)) + if (allocated(keeps%omega)) keeps%omega(:) = pack(keeps%omega(:), .not. lspill_list(:)) + if (allocated(keeps%capm)) keeps%capm(:) = pack(keeps%capm(:), .not. lspill_list(:)) + + if (allocated(keeps%aobl)) then + do i = 1, NDIM + keeps%aobl(i, :) = pack(keeps%aobl(i, :), .not. lspill_list(:)) + end do + end if + + if (allocated(keeps%agr)) then + do i = 1, NDIM + keeps%agr(i, :) = pack(keeps%agr(i, :), .not. lspill_list(:)) + end do + end if + + if (allocated(keeps%atide)) then + do i = 1, NDIM + keeps%atide(i, :) = pack(keeps%atide(i, :), .not. lspill_list(:)) + end do + end if + + end if + ! This is the base class, so will be the last to be called in the cascade. + ! Therefore we need to set the nbody values for both the keeps and discareds + discards%nbody = count(lspill_list(:)) + keeps%nbody = count(.not.lspill_list(:)) + if (allocated(keeps%ldiscard)) deallocate(keeps%ldiscard) + if (allocated(discards%ldiscard)) deallocate(discards%ldiscard) + allocate(keeps%ldiscard(keeps%nbody)) + allocate(discards%ldiscard(discards%nbody)) + keeps%ldiscard = .false. + discards%ldiscard = .true. + + end associate + + return + end subroutine util_copy_spill_body + + + module subroutine util_copy_spill_pl(self, discards, lspill_list) + !! author: David A. Minton + !! + !! Move spilled (discarded) Swiftest massive body structure from active list to discard list + !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 + implicit none + ! Arguments + 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 + ! Internals + integer(I4B) :: i + + associate(keeps => self) + + select type (discards) ! The standard requires us to select the type of both arguments in order to access all the components + class is (swiftest_pl) + !> Spill components specific to the massive body class + discards%mass(:) = pack(keeps%mass(:), lspill_list(:)) + discards%Gmass(:) = pack(keeps%Gmass(:), lspill_list(:)) + discards%rhill(:) = pack(keeps%rhill(:), lspill_list(:)) + + if (allocated(keeps%radius)) discards%radius(:) = pack(keeps%radius(:), lspill_list(:)) + if (allocated(keeps%density)) discards%density(:) = pack(keeps%density(:), lspill_list(:)) + if (allocated(keeps%k2)) discards%k2(:) = pack(keeps%k2(:), lspill_list(:)) + if (allocated(keeps%Q)) discards%Q(:) = pack(keeps%Q(:), lspill_list(:)) + if (allocated(keeps%tlag)) discards%tlag(:) = pack(keeps%tlag(:), lspill_list(:)) + + if (allocated(keeps%xbeg)) then + do i = 1, NDIM + discards%xbeg(i, :) = pack(keeps%xbeg(i, :), lspill_list(:)) + end do + end if + + if (allocated(keeps%xend)) then + do i = 1, NDIM + discards%xend(i, :) = pack(keeps%xend(i, :), lspill_list(:)) + end do + end if + + if (allocated(keeps%vbeg)) then + do i = 1, NDIM + discards%vbeg(i, :) = pack(keeps%vbeg(i, :), lspill_list(:)) + end do + end if + + if (allocated(keeps%Ip)) then + do i = 1, NDIM + discards%Ip(i, :) = pack(keeps%Ip(i, :), lspill_list(:)) + end do + end if + + if (allocated(keeps%rot)) then + do i = 1, NDIM + discards%rot(i, :) = pack(keeps%rot(i, :), lspill_list(:)) + end do + end if + + if (count(.not.lspill_list(:)) > 0) then + keeps%mass(:) = pack(keeps%mass(:), .not. lspill_list(:)) + keeps%Gmass(:) = pack(keeps%Gmass(:), .not. lspill_list(:)) + keeps%rhill(:) = pack(keeps%rhill(:), .not. lspill_list(:)) + if (allocated(keeps%radius)) keeps%radius(:) = pack(keeps%radius(:), .not. lspill_list(:)) + if (allocated(keeps%density)) keeps%density(:) = pack(keeps%density(:), .not. lspill_list(:)) + if (allocated(keeps%k2)) keeps%k2(:) = pack(keeps%k2(:), .not. lspill_list(:)) + if (allocated(keeps%Q)) keeps%Q(:) = pack(keeps%Q(:), .not. lspill_list(:)) + if (allocated(keeps%tlag)) keeps%tlag(:) = pack(keeps%tlag(:), .not. lspill_list(:)) + + if (allocated(keeps%xbeg)) then + do i = 1, NDIM + keeps%xbeg(i,:) = pack(keeps%xbeg(i,:), .not. lspill_list(:)) + end do + end if + + if (allocated(keeps%xend)) then + do i = 1, NDIM + keeps%xend(i,:) = pack(keeps%xend(i,:), .not. lspill_list(:)) + end do + end if + + if (allocated(keeps%vbeg)) then + do i = 1, NDIM + keeps%vbeg(i,:) = pack(keeps%vbeg(i,:), .not. lspill_list(:)) + end do + end if + + if (allocated(keeps%Ip)) then + do i = 1, NDIM + keeps%Ip(i,:) = pack(keeps%Ip(i,:), .not. lspill_list(:)) + end do + end if + + if (allocated(keeps%rot)) then + do i = 1, NDIM + keeps%rot(i,:) = pack(keeps%rot(i,:), .not. lspill_list(:)) + end do + end if + + end if + + call util_copy_spill_body(keeps, discards, lspill_list) + class default + write(*,*) 'Error! spill method called for incompatible return type on swiftest_pl' + end select + end associate + + return + end subroutine util_copy_spill_pl + + + module subroutine util_copy_spill_tp(self, discards, lspill_list) + !! author: David A. Minton + !! + !! Move spilled (discarded) Swiftest test particle structure from active list to discard list + !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 + implicit none + ! Arguments + 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 discardse + + associate(keeps => self, ntp => self%nbody) + select type(discards) + class is (swiftest_tp) + !> Spill components specific to the test particle class + discards%isperi(:) = pack(keeps%isperi(:), lspill_list(:)) + discards%peri(:) = pack(keeps%peri(:), lspill_list(:)) + discards%atp(:) = pack(keeps%atp(:), lspill_list(:)) + if (count(.not.lspill_list(:)) > 0) then + keeps%atp(:) = pack(keeps%atp(:), .not. lspill_list(:)) + keeps%peri(:) = pack(keeps%peri(:), .not. lspill_list(:)) + keeps%isperi(:) = pack(keeps%isperi(:), .not. lspill_list(:)) + end if + call util_copy_spill_body(keeps, discards, lspill_list) + class default + write(*,*) 'Error! spill method called for incompatible return type on swiftest_tp' + end select + end associate + + return + end subroutine util_copy_spill_tp + end submodule s_util_copy \ No newline at end of file diff --git a/src/util/util_spill_and_fill.f90 b/src/util/util_spill_and_fill.f90 deleted file mode 100644 index 89f8bb095..000000000 --- a/src/util/util_spill_and_fill.f90 +++ /dev/null @@ -1,506 +0,0 @@ -submodule (swiftest_classes) s_util_spill_and_fill - use swiftest -contains - - module subroutine util_spill_body(self, discards, lspill_list) - !! author: David A. Minton - !! - !! Move spilled (discarded) Swiftest generic particle structure from active list to discard list - !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 - implicit none - ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest generic 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 - ! Internals - integer(I4B) :: i - - ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps - !> Spill all the common components - associate(keeps => self) - discards%id(:) = pack(keeps%id(:), lspill_list(:)) - discards%name(:) = pack(keeps%name(:), lspill_list(:)) - discards%status(:) = pack(keeps%status(:), lspill_list(:)) - discards%mu(:) = pack(keeps%mu(:), lspill_list(:)) - discards%lmask(:) = pack(keeps%lmask(:), lspill_list(:)) - do i = 1, NDIM - discards%xh(i, :) = pack(keeps%xh(i, :), lspill_list(:)) - discards%vh(i, :) = pack(keeps%vh(i, :), lspill_list(:)) - discards%xb(i, :) = pack(keeps%xb(i, :), lspill_list(:)) - discards%vb(i, :) = pack(keeps%vb(i, :), lspill_list(:)) - discards%ah(i, :) = pack(keeps%ah(i, :), lspill_list(:)) - end do - - if (allocated(keeps%a)) discards%a(:) = pack(keeps%a(:), lspill_list(:)) - if (allocated(keeps%e)) discards%e(:) = pack(keeps%e(:), lspill_list(:)) - if (allocated(keeps%capom)) discards%capom(:) = pack(keeps%capom(:), lspill_list(:)) - if (allocated(keeps%omega)) discards%omega(:) = pack(keeps%omega(:), lspill_list(:)) - if (allocated(keeps%capm)) discards%capm(:) = pack(keeps%capm(:), lspill_list(:)) - - - if (allocated(keeps%aobl)) then - do i = 1, NDIM - discards%aobl(i, :) = pack(keeps%aobl(i, :), lspill_list(:)) - end do - end if - if (allocated(keeps%agr)) then - do i = 1, NDIM - discards%agr(i, :) = pack(keeps%agr(i, :), lspill_list(:)) - end do - end if - if (allocated(keeps%atide)) then - do i = 1, NDIM - discards%atide(i, :) = pack(keeps%atide(i, :), lspill_list(:)) - end do - end if - - if (count(.not.lspill_list(:)) > 0) then - keeps%id(:) = pack(keeps%id(:), .not. lspill_list(:)) - keeps%name(:) = pack(keeps%name(:), .not. lspill_list(:)) - keeps%status(:) = pack(keeps%status(:), .not. lspill_list(:)) - keeps%mu(:) = pack(keeps%mu(:), .not. lspill_list(:)) - keeps%lmask(:) = pack(keeps%lmask(:), .not. lspill_list(:)) - - do i = 1, NDIM - keeps%xh(i, :) = pack(keeps%xh(i, :), .not. lspill_list(:)) - keeps%vh(i, :) = pack(keeps%vh(i, :), .not. lspill_list(:)) - keeps%xb(i, :) = pack(keeps%xb(i, :), .not. lspill_list(:)) - keeps%vb(i, :) = pack(keeps%vb(i, :), .not. lspill_list(:)) - keeps%ah(i, :) = pack(keeps%ah(i, :), .not. lspill_list(:)) - end do - - if (allocated(keeps%a)) keeps%a(:) = pack(keeps%a(:), .not. lspill_list(:)) - if (allocated(keeps%e)) keeps%e(:) = pack(keeps%e(:), .not. lspill_list(:)) - if (allocated(keeps%inc)) keeps%inc(:) = pack(keeps%inc(:), .not. lspill_list(:)) - if (allocated(keeps%capom)) keeps%capom(:) = pack(keeps%capom(:), .not. lspill_list(:)) - if (allocated(keeps%omega)) keeps%omega(:) = pack(keeps%omega(:), .not. lspill_list(:)) - if (allocated(keeps%capm)) keeps%capm(:) = pack(keeps%capm(:), .not. lspill_list(:)) - - if (allocated(keeps%aobl)) then - do i = 1, NDIM - keeps%aobl(i, :) = pack(keeps%aobl(i, :), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%agr)) then - do i = 1, NDIM - keeps%agr(i, :) = pack(keeps%agr(i, :), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%atide)) then - do i = 1, NDIM - keeps%atide(i, :) = pack(keeps%atide(i, :), .not. lspill_list(:)) - end do - end if - - end if - ! This is the base class, so will be the last to be called in the cascade. - ! Therefore we need to set the nbody values for both the keeps and discareds - discards%nbody = count(lspill_list(:)) - keeps%nbody = count(.not.lspill_list(:)) - if (allocated(keeps%ldiscard)) deallocate(keeps%ldiscard) - if (allocated(discards%ldiscard)) deallocate(discards%ldiscard) - allocate(keeps%ldiscard(keeps%nbody)) - allocate(discards%ldiscard(discards%nbody)) - keeps%ldiscard = .false. - discards%ldiscard = .true. - - end associate - - return - end subroutine util_spill_body - - - module subroutine util_fill_body(self, inserts, lfill_list) - !! author: David A. Minton - !! - !! Insert new Swiftest generic particle structure into an old one. - !! This is the inverse of a fill operation. - implicit none - ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest generic body object - class(swiftest_body), intent(inout) :: inserts !! Insertted object - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps - ! internals - integer(I4B) :: i - - ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps - !> Spill all the common components - associate(keeps => self) - keeps%id(:) = unpack(keeps%id(:), .not.lfill_list(:), keeps%id(:)) - keeps%id(:) = unpack(inserts%id(:), lfill_list(:), keeps%id(:)) - - keeps%name(:) = unpack(keeps%name(:), .not.lfill_list(:), keeps%name(:)) - keeps%name(:) = unpack(inserts%name(:), lfill_list(:), keeps%name(:)) - - keeps%status(:) = unpack(keeps%status(:), .not.lfill_list(:), keeps%status(:)) - keeps%status(:) = unpack(inserts%status(:), lfill_list(:), keeps%status(:)) - - keeps%ldiscard(:) = unpack(keeps%ldiscard(:), .not.lfill_list(:), keeps%ldiscard(:)) - keeps%ldiscard(:) = unpack(inserts%ldiscard(:), lfill_list(:), keeps%ldiscard(:)) - - keeps%mu(:) = unpack(keeps%mu(:), .not.lfill_list(:), keeps%mu(:)) - keeps%mu(:) = unpack(inserts%mu(:), lfill_list(:), keeps%mu(:)) - - keeps%lmask(:) = unpack(keeps%lmask(:), .not.lfill_list(:), keeps%ldiscard(:)) - keeps%lmask(:) = unpack(inserts%lmask(:), lfill_list(:), keeps%ldiscard(:)) - - do i = 1, NDIM - keeps%xh(i, :) = unpack(keeps%xh(i, :), .not.lfill_list(:), keeps%xh(i, :)) - keeps%xh(i, :) = unpack(inserts%xh(i, :), lfill_list(:), keeps%xh(i, :)) - - keeps%vh(i, :) = unpack(keeps%vh(i, :), .not.lfill_list(:), keeps%vh(i, :)) - keeps%vh(i, :) = unpack(inserts%vh(i, :), lfill_list(:), keeps%vh(i, :)) - - keeps%xb(i, :) = unpack(keeps%xb(i, :), .not.lfill_list(:), keeps%xb(i, :)) - keeps%xb(i, :) = unpack(inserts%xb(i, :), lfill_list(:), keeps%xb(i, :)) - - keeps%vb(i, :) = unpack(keeps%vb(i, :), .not.lfill_list(:), keeps%vb(i, :)) - keeps%vb(i, :) = unpack(inserts%vb(i, :), lfill_list(:), keeps%vb(i, :)) - - keeps%ah(i, :) = unpack(keeps%ah(i, :), .not.lfill_list(:), keeps%ah(i, :)) - keeps%ah(i, :) = unpack(inserts%ah(i, :), lfill_list(:), keeps%ah(i, :)) - end do - - if (allocated(keeps%aobl)) then - do i = 1, NDIM - keeps%aobl(i, :) = unpack(keeps%aobl(i, :), .not.lfill_list(:), keeps%aobl(i, :)) - keeps%aobl(i, :) = unpack(inserts%aobl(i, :), lfill_list(:), keeps%aobl(i, :)) - end do - end if - - if (allocated(keeps%agr)) then - do i = 1, NDIM - keeps%agr(i, :) = unpack(keeps%agr(i, :), .not.lfill_list(:), keeps%agr(i, :)) - keeps%agr(i, :) = unpack(inserts%agr(i, :), lfill_list(:), keeps%agr(i, :)) - end do - end if - - if (allocated(keeps%atide)) then - do i = 1, NDIM - keeps%atide(i, :) = unpack(keeps%atide(i, :), .not.lfill_list(:), keeps%atide(i, :)) - keeps%atide(i, :) = unpack(inserts%atide(i, :), lfill_list(:), keeps%atide(i, :)) - end do - end if - - if (allocated(keeps%a)) then - keeps%a(:) = unpack(keeps%a(:), .not.lfill_list(:), keeps%a(:)) - keeps%a(:) = unpack(inserts%a(:), lfill_list(:), keeps%a(:)) - end if - - if (allocated(keeps%e)) then - keeps%e(:) = unpack(keeps%e(:), .not.lfill_list(:), keeps%e(:)) - keeps%e(:) = unpack(inserts%e(:), lfill_list(:), keeps%e(:)) - end if - - if (allocated(keeps%inc)) then - keeps%inc(:) = unpack(keeps%inc(:), .not.lfill_list(:), keeps%inc(:)) - keeps%inc(:) = unpack(inserts%inc(:), lfill_list(:), keeps%inc(:)) - end if - - if (allocated(keeps%capom)) then - keeps%capom(:) = unpack(keeps%capom(:),.not.lfill_list(:), keeps%capom(:)) - keeps%capom(:) = unpack(inserts%capom(:),lfill_list(:), keeps%capom(:)) - end if - - if (allocated(keeps%omega)) then - keeps%omega(:) = unpack(keeps%omega(:),.not.lfill_list(:), keeps%omega(:)) - keeps%omega(:) = unpack(inserts%omega(:),lfill_list(:), keeps%omega(:)) - end if - - if (allocated(keeps%capm)) then - keeps%capm(:) = unpack(keeps%capm(:), .not.lfill_list(:), keeps%capm(:)) - keeps%capm(:) = unpack(inserts%capm(:), lfill_list(:), keeps%capm(:)) - end if - - ! This is the base class, so will be the last to be called in the cascade. - keeps%nbody = size(keeps%id(:)) - end associate - - return - end subroutine util_fill_body - - - module subroutine util_spill_pl(self, discards, lspill_list) - !! author: David A. Minton - !! - !! Move spilled (discarded) Swiftest massive body structure from active list to discard list - !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 - implicit none - ! Arguments - 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 - ! Internals - integer(I4B) :: i - - associate(keeps => self) - - select type (discards) ! The standard requires us to select the type of both arguments in order to access all the components - class is (swiftest_pl) - !> Spill components specific to the massive body class - discards%mass(:) = pack(keeps%mass(:), lspill_list(:)) - discards%Gmass(:) = pack(keeps%Gmass(:), lspill_list(:)) - discards%rhill(:) = pack(keeps%rhill(:), lspill_list(:)) - - if (allocated(keeps%radius)) discards%radius(:) = pack(keeps%radius(:), lspill_list(:)) - if (allocated(keeps%density)) discards%density(:) = pack(keeps%density(:), lspill_list(:)) - if (allocated(keeps%k2)) discards%k2(:) = pack(keeps%k2(:), lspill_list(:)) - if (allocated(keeps%Q)) discards%Q(:) = pack(keeps%Q(:), lspill_list(:)) - if (allocated(keeps%tlag)) discards%tlag(:) = pack(keeps%tlag(:), lspill_list(:)) - - if (allocated(keeps%xbeg)) then - do i = 1, NDIM - discards%xbeg(i, :) = pack(keeps%xbeg(i, :), lspill_list(:)) - end do - end if - - if (allocated(keeps%xend)) then - do i = 1, NDIM - discards%xend(i, :) = pack(keeps%xend(i, :), lspill_list(:)) - end do - end if - - if (allocated(keeps%vbeg)) then - do i = 1, NDIM - discards%vbeg(i, :) = pack(keeps%vbeg(i, :), lspill_list(:)) - end do - end if - - if (allocated(keeps%Ip)) then - do i = 1, NDIM - discards%Ip(i, :) = pack(keeps%Ip(i, :), lspill_list(:)) - end do - end if - - if (allocated(keeps%rot)) then - do i = 1, NDIM - discards%rot(i, :) = pack(keeps%rot(i, :), lspill_list(:)) - end do - end if - - if (count(.not.lspill_list(:)) > 0) then - keeps%mass(:) = pack(keeps%mass(:), .not. lspill_list(:)) - keeps%Gmass(:) = pack(keeps%Gmass(:), .not. lspill_list(:)) - keeps%rhill(:) = pack(keeps%rhill(:), .not. lspill_list(:)) - if (allocated(keeps%radius)) keeps%radius(:) = pack(keeps%radius(:), .not. lspill_list(:)) - if (allocated(keeps%density)) keeps%density(:) = pack(keeps%density(:), .not. lspill_list(:)) - if (allocated(keeps%k2)) keeps%k2(:) = pack(keeps%k2(:), .not. lspill_list(:)) - if (allocated(keeps%Q)) keeps%Q(:) = pack(keeps%Q(:), .not. lspill_list(:)) - if (allocated(keeps%tlag)) keeps%tlag(:) = pack(keeps%tlag(:), .not. lspill_list(:)) - - if (allocated(keeps%xbeg)) then - do i = 1, NDIM - keeps%xbeg(i,:) = pack(keeps%xbeg(i,:), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%xend)) then - do i = 1, NDIM - keeps%xend(i,:) = pack(keeps%xend(i,:), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%vbeg)) then - do i = 1, NDIM - keeps%vbeg(i,:) = pack(keeps%vbeg(i,:), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%Ip)) then - do i = 1, NDIM - keeps%Ip(i,:) = pack(keeps%Ip(i,:), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%rot)) then - do i = 1, NDIM - keeps%rot(i,:) = pack(keeps%rot(i,:), .not. lspill_list(:)) - end do - end if - - end if - - call util_spill_body(keeps, discards, lspill_list) - class default - write(*,*) 'Error! spill method called for incompatible return type on swiftest_pl' - end select - end associate - - return - end subroutine util_spill_pl - - - module subroutine util_fill_pl(self, inserts, lfill_list) - !! author: David A. Minton - !! - !! Insert new Swiftest massive body structure into an old one. - !! This is the inverse of a fill operation. - implicit none - ! Arguments - class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object - class(swiftest_body), intent(inout) :: inserts !! Swiftest body object to be inserted - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps - ! Internals - integer(I4B) :: i - - associate(keeps => self) - - select type (inserts) ! The standard requires us to select the type of both arguments in order to access all the components - class is (swiftest_pl) - !> Spill components specific to the massive body class - keeps%mass(:) = unpack(keeps%mass(:),.not.lfill_list(:), keeps%mass(:)) - keeps%mass(:) = unpack(inserts%mass(:),lfill_list(:), keeps%mass(:)) - - keeps%Gmass(:) = unpack(keeps%Gmass(:),.not.lfill_list(:), keeps%Gmass(:)) - keeps%Gmass(:) = unpack(inserts%Gmass(:),lfill_list(:), keeps%Gmass(:)) - - keeps%rhill(:) = unpack(keeps%rhill(:),.not.lfill_list(:), keeps%rhill(:)) - keeps%rhill(:) = unpack(inserts%rhill(:),lfill_list(:), keeps%rhill(:)) - - if (allocated(keeps%radius) .and. allocated(inserts%radius)) then - keeps%radius(:) = unpack(keeps%radius(:),.not.lfill_list(:), keeps%radius(:)) - keeps%radius(:) = unpack(inserts%radius(:),lfill_list(:), keeps%radius(:)) - end if - - if (allocated(keeps%density) .and. allocated(inserts%density)) then - keeps%density(:) = unpack(keeps%density(:),.not.lfill_list(:), keeps%density(:)) - keeps%density(:) = unpack(inserts%density(:),lfill_list(:), keeps%density(:)) - end if - - if (allocated(keeps%k2) .and. allocated(inserts%k2)) then - keeps%k2(:) = unpack(keeps%k2(:),.not.lfill_list(:), keeps%k2(:)) - keeps%k2(:) = unpack(inserts%k2(:),lfill_list(:), keeps%k2(:)) - end if - - if (allocated(keeps%Q) .and. allocated(inserts%Q)) then - keeps%Q(:) = unpack(keeps%Q(:),.not.lfill_list(:), keeps%Q(:)) - keeps%Q(:) = unpack(inserts%Q(:),lfill_list(:), keeps%Q(:)) - end if - - if (allocated(keeps%tlag) .and. allocated(inserts%tlag)) then - keeps%tlag(:) = unpack(keeps%tlag(:),.not.lfill_list(:), keeps%tlag(:)) - keeps%tlag(:) = unpack(inserts%tlag(:),lfill_list(:), keeps%tlag(:)) - end if - - if (allocated(keeps%xbeg) .and. allocated(inserts%xbeg)) then - do i = 1, NDIM - keeps%xbeg(i, :) = unpack(keeps%xbeg(i, :), .not.lfill_list(:), keeps%xbeg(i, :)) - keeps%xbeg(i, :) = unpack(inserts%xbeg(i, :), lfill_list(:), keeps%xbeg(i, :)) - end do - end if - - if (allocated(keeps%xend) .and. allocated(inserts%xend)) then - do i = 1, NDIM - keeps%xend(i, :) = unpack(keeps%xend(i, :), .not.lfill_list(:), keeps%xend(i, :)) - keeps%xend(i, :) = unpack(inserts%xend(i, :), lfill_list(:), keeps%xend(i, :)) - end do - end if - - if (allocated(keeps%vbeg) .and. allocated(inserts%vbeg)) then - do i = 1, NDIM - keeps%vbeg(i, :) = unpack(keeps%vbeg(i, :), .not.lfill_list(:), keeps%vbeg(i, :)) - keeps%vbeg(i, :) = unpack(inserts%vbeg(i, :), lfill_list(:), keeps%vbeg(i, :)) - end do - end if - - if (allocated(keeps%Ip) .and. allocated(inserts%Ip)) then - do i = 1, NDIM - keeps%Ip(i, :) = unpack(keeps%Ip(i, :), .not.lfill_list(:), keeps%Ip(i, :)) - keeps%Ip(i, :) = unpack(inserts%Ip(i, :), lfill_list(:), keeps%Ip(i, :)) - end do - end if - - if (allocated(keeps%rot) .and. allocated(inserts%rot)) then - do i = 1, NDIM - keeps%rot(i, :) = unpack(keeps%rot(i, :), .not.lfill_list(:), keeps%rot(i, :)) - keeps%rot(i, :) = unpack(inserts%rot(i, :), lfill_list(:), keeps%rot(i, :)) - end do - end if - - keeps%ldiscard(:) = unpack(inserts%ldiscard(:), lfill_list(:), keeps%ldiscard(:)) - - call util_fill_body(keeps, inserts, lfill_list) - class default - write(*,*) 'Error! fill method called for incompatible return type on swiftest_pl' - end select - end associate - - return - end subroutine util_fill_pl - - - module subroutine util_spill_tp(self, discards, lspill_list) - !! author: David A. Minton - !! - !! Move spilled (discarded) Swiftest test particle structure from active list to discard list - !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 - implicit none - ! Arguments - 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 discardse - - associate(keeps => self, ntp => self%nbody) - select type(discards) - class is (swiftest_tp) - !> Spill components specific to the test particle class - discards%isperi(:) = pack(keeps%isperi(:), lspill_list(:)) - discards%peri(:) = pack(keeps%peri(:), lspill_list(:)) - discards%atp(:) = pack(keeps%atp(:), lspill_list(:)) - if (count(.not.lspill_list(:)) > 0) then - keeps%atp(:) = pack(keeps%atp(:), .not. lspill_list(:)) - keeps%peri(:) = pack(keeps%peri(:), .not. lspill_list(:)) - keeps%isperi(:) = pack(keeps%isperi(:), .not. lspill_list(:)) - end if - call util_spill_body(keeps, discards, lspill_list) - class default - write(*,*) 'Error! spill method called for incompatible return type on swiftest_tp' - end select - end associate - - return - end subroutine util_spill_tp - - - module subroutine util_fill_tp(self, inserts, lfill_list) - !! author: David A. Minton - !! - !! Insert new Swiftest test particle structure into an old one. - !! This is the inverse of a fill operation. - implicit none - ! Arguments - class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object - class(swiftest_body), intent(inout) :: inserts !! Swiftest body object to be inserted - logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps - - associate(keeps => self) - select type(inserts) - class is (swiftest_tp) - !> Spill components specific to the test particle class - keeps%isperi(:) = unpack(keeps%isperi(:), .not.lfill_list(:), keeps%isperi(:)) - keeps%isperi(:) = unpack(inserts%isperi(:), lfill_list(:), keeps%isperi(:)) - - keeps%peri(:) = unpack(keeps%peri(:), .not.lfill_list(:), keeps%peri(:)) - keeps%peri(:) = unpack(inserts%peri(:), lfill_list(:), keeps%peri(:)) - - keeps%atp(:) = unpack(keeps%atp(:), .not.lfill_list(:), keeps%atp(:)) - keeps%atp(:) = unpack(inserts%atp(:), lfill_list(:), keeps%atp(:)) - - call util_fill_body(keeps, inserts, lfill_list) - class default - write(*,*) 'Error! fill method called for incompatible return type on swiftest_tp' - end select - end associate - - return - end subroutine util_fill_tp - -end submodule s_util_spill_and_fill - - - - - - diff --git a/src/whm/whm_util.f90 b/src/whm/whm_util.f90 index 779480b3f..aaad01e84 100644 --- a/src/whm/whm_util.f90 +++ b/src/whm/whm_util.f90 @@ -2,7 +2,7 @@ use swiftest contains - module subroutine whm_util_spill_pl(self, discards, lspill_list) + module subroutine whm_util_copy_spill_pl(self, discards, lspill_list) !! author: David A. Minton !! !! Move spilled (discarded) WHM test particle structure from active list to discard list @@ -35,17 +35,17 @@ module subroutine whm_util_spill_pl(self, discards, lspill_list) keeps%vj(i, :) = pack(keeps%vj(i, :), .not. lspill_list(:)) end do end if - call util_spill_pl(keeps, discards, lspill_list) + call util_copy_spill_pl(keeps, discards, lspill_list) class default write(*,*) 'Error! spill method called for incompatible return type on whm_pl' end select end associate return - end subroutine whm_util_spill_pl + end subroutine whm_util_copy_spill_pl - module subroutine whm_util_fill_pl(self, inserts, lfill_list) + module subroutine whm_util_copy_fill_pl(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new WHM test particle structure into an old one. @@ -55,7 +55,7 @@ module subroutine whm_util_fill_pl(self, inserts, lfill_list) implicit none ! Arguments class(whm_pl), intent(inout) :: self !! WHM massive body object - class(swiftest_body), intent(inout) :: inserts !! inserted object + class(swiftest_body), intent(in) :: inserts !! inserted object logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps ! Internals integer(I4B) :: i @@ -80,14 +80,14 @@ module subroutine whm_util_fill_pl(self, inserts, lfill_list) keeps%vj(i, :) = unpack(keeps%vj(i, :), .not.lfill_list(:), keeps%vj(i, :)) keeps%vj(i, :) = unpack(inserts%vj(i, :), lfill_list(:), keeps%vj(i, :)) end do - call util_fill_pl(keeps, inserts, lfill_list) + call util_copy_fill_pl(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on whm_pl' end select end associate return - end subroutine whm_util_fill_pl + end subroutine whm_util_copy_fill_pl module subroutine whm_util_set_ir3j(self) From fc45a69416e851f2e1065f53c49992bb5f8778e1 Mon Sep 17 00:00:00 2001 From: David Minton Date: Sat, 31 Jul 2021 16:26:52 -0400 Subject: [PATCH 04/42] Added fill method to SyMBA --- src/modules/rmvs_classes.f90 | 4 +- src/modules/swiftest_classes.f90 | 6 +-- src/modules/symba_classes.f90 | 18 +++++++ src/modules/whm_classes.f90 | 2 +- src/symba/symba_util.f90 | 93 ++++++++++++++++++++++++++++++++ src/util/util_copy.f90 | 1 - 6 files changed, 117 insertions(+), 7 deletions(-) diff --git a/src/modules/rmvs_classes.f90 b/src/modules/rmvs_classes.f90 index 945b96ce2..64a0a5875 100644 --- a/src/modules/rmvs_classes.f90 +++ b/src/modules/rmvs_classes.f90 @@ -71,7 +71,7 @@ module rmvs_classes procedure :: accel => rmvs_kick_getacch_tp !! Calculates either the standard or modified version of the acceleration depending if the !! if the test particle is undergoing a close encounter or not procedure :: setup => rmvs_setup_tp !! Constructor method - Allocates space for number of particles - procedure :: fill => rmvs_util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => rmvs_util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: sort => rmvs_util_sort_tp !! Sorts body arrays by a sortable componen procedure :: rearrange => rmvs_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods procedure :: spill => rmvs_util_copy_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) @@ -94,7 +94,7 @@ module rmvs_classes procedure :: setup => rmvs_setup_pl !! Constructor method - Allocates space for number of particles procedure :: sort => rmvs_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => rmvs_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: fill => rmvs_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => rmvs_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: spill => rmvs_util_copy_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type rmvs_pl diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 5ec4fc7dc..3711e5295 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -166,7 +166,7 @@ module swiftest_classes procedure :: accel_user => user_kick_getacch_body !! Add user-supplied heliocentric accelerations to planets procedure :: append => util_append_body !! Appends elements from one structure to another procedure :: copy_into => util_copy_into_body !! Copies elements from one Swiftest body object to another. - procedure :: fill => util_copy_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => util_copy_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => 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 => util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) procedure :: sort => util_sort_body !! Sorts body arrays by a sortable componen @@ -208,7 +208,7 @@ module swiftest_classes procedure :: accel_tides => tides_kick_getacch_pl !! Compute the accelerations of bodies due to tidal interactions with the central body procedure :: h2b => util_coord_h2b_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) procedure :: b2h => util_coord_b2h_pl !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) - procedure :: fill => util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: set_beg_end => util_set_beg_end_pl !! Sets the beginning and ending positions and velocities of planets. procedure :: set_mu => util_set_mu_pl !! Method used to construct the vectorized form of the central body mass procedure :: set_rhill => util_set_rhill !! Calculates the Hill's radii for each body @@ -237,7 +237,7 @@ module swiftest_classes procedure :: setup => setup_tp !! A base constructor that sets the number of bodies and procedure :: h2b => util_coord_h2b_tp !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) procedure :: b2h => util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) - procedure :: fill => util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: get_peri => util_peri_tp !! Determine system pericenter passages for test particles procedure :: set_mu => util_set_mu_tp !! Method used to construct the vectorized form of the central body mass procedure :: sort => util_sort_tp !! Sorts body arrays by a sortable component diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 2b131ef76..6a878520a 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -92,6 +92,7 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_pl !! Checks if massive bodies are going through close encounters with each other procedure :: accel => symba_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies procedure :: setup => symba_setup_pl !! Constructor method - Allocates space for number of particle + procedure :: fill => symba_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: sort => symba_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods end type symba_pl @@ -109,6 +110,7 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_tp !! Checks if any test particles are undergoing a close encounter with a massive body procedure :: accel => symba_kick_getacch_tp !! Compute heliocentric accelerations of test particles procedure :: setup => symba_setup_tp !! Constructor method - Allocates space for number of particle + procedure :: fill => symba_util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: sort => symba_util_sort_tp !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods end type symba_tp @@ -414,6 +416,22 @@ module subroutine symba_step_reset_system(self) class(symba_nbody_system), intent(inout) :: self !! SyMBA nbody system object end subroutine symba_step_reset_system + module subroutine symba_util_copy_fill_pl(self, inserts, lfill_list) + use swiftest_classes, only : swiftest_body + implicit none + class(symba_pl), intent(inout) :: self !! SyMBA massive 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 + end subroutine symba_util_copy_fill_pl + + module subroutine symba_util_copy_fill_tp(self, inserts, lfill_list) + use swiftest_classes, only : swiftest_body + implicit none + 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 + end subroutine symba_util_copy_fill_tp + module subroutine symba_util_copy_pltpenc(self, source) implicit none class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list diff --git a/src/modules/whm_classes.f90 b/src/modules/whm_classes.f90 index d64354c08..4dd7f646a 100644 --- a/src/modules/whm_classes.f90 +++ b/src/modules/whm_classes.f90 @@ -34,7 +34,7 @@ module whm_classes procedure :: j2h => whm_coord_j2h_pl !! Convert position and velcoity vectors from Jacobi to helliocentric coordinates procedure :: vh2vj => whm_coord_vh2vj_pl !! Convert velocity vectors from heliocentric to Jacobi coordinates procedure :: drift => whm_drift_pl !! Loop through massive bodies and call Danby drift routine to jacobi coordinates - procedure :: fill => whm_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the MERGE intrinsic) + procedure :: fill => whm_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: accel => whm_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies procedure :: kick => whm_kick_vh_pl !! Kick heliocentric velocities of massive bodies procedure :: accel_gr => whm_gr_kick_getacch_pl !! Acceleration term arising from the post-Newtonian correction diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 7a6f17cbf..b8dbbd49a 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -2,6 +2,99 @@ use swiftest contains + module subroutine symba_util_copy_fill_pl(self, inserts, lfill_list) + !! author: David A. Minton + !! + !! Insert new SyMBA test particle structure into an old one. + !! This is the inverse of a fill operation. + !! + 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 + + associate(keeps => self) + select type(inserts) + class is (symba_pl) + keeps%lcollision(:) = unpack(keeps%lcollision(:), .not.lfill_list(:), keeps%lcollision(:)) + keeps%lcollision(:) = unpack(inserts%lcollision(:), lfill_list(:), keeps%lcollision(:)) + + keeps%lencounter(:) = unpack(keeps%lencounter(:), .not.lfill_list(:), keeps%lencounter(:)) + keeps%lencounter(:) = unpack(inserts%lencounter(:), lfill_list(:), keeps%lencounter(:)) + + keeps%lmtiny(:) = unpack(keeps%lmtiny(:), .not.lfill_list(:), keeps%lmtiny(:)) + keeps%lmtiny(:) = unpack(inserts%lmtiny(:), lfill_list(:), keeps%lmtiny(:)) + + keeps%nplenc(:) = unpack(keeps%nplenc(:), .not.lfill_list(:), keeps%nplenc(:)) + keeps%nplenc(:) = unpack(inserts%nplenc(:), lfill_list(:), keeps%nplenc(:)) + + keeps%nplenc(:) = unpack(keeps%nplenc(:), .not.lfill_list(:), keeps%nplenc(:)) + keeps%ntpenc(:) = unpack(inserts%ntpenc(:), lfill_list(:), keeps%ntpenc(:)) + + keeps%levelg(:) = unpack(keeps%levelg(:), .not.lfill_list(:), keeps%levelg(:)) + keeps%levelg(:) = unpack(inserts%levelg(:), lfill_list(:), keeps%levelg(:)) + + keeps%levelm(:) = unpack(keeps%levelm(:), .not.lfill_list(:), keeps%levelm(:)) + keeps%levelm(:) = unpack(inserts%levelm(:), lfill_list(:), keeps%levelm(:)) + + keeps%isperi(:) = unpack(keeps%isperi(:), .not.lfill_list(:), keeps%isperi(:)) + keeps%isperi(:) = unpack(inserts%isperi(:), lfill_list(:), keeps%isperi(:)) + + keeps%peri(:) = unpack(keeps%peri(:), .not.lfill_list(:), keeps%peri(:)) + keeps%peri(:) = unpack(inserts%peri(:), lfill_list(:), keeps%peri(:)) + + keeps%atp(:) = unpack(keeps%atp(:), .not.lfill_list(:), keeps%atp(:)) + keeps%atp(:) = unpack(inserts%atp(:), lfill_list(:), keeps%atp(:)) + + keeps%kin(:) = unpack(keeps%kin(:), .not.lfill_list(:), keeps%kin(:)) + keeps%kin(:) = unpack(inserts%kin(:), lfill_list(:), keeps%kin(:)) + + keeps%info(:) = unpack(keeps%info(:), .not.lfill_list(:), keeps%info(:)) + keeps%info(:) = unpack(inserts%info(:), lfill_list(:), keeps%info(:)) + + call util_copy_fill_pl(keeps, inserts, lfill_list) + class default + write(*,*) 'Error! fill method called for incompatible return type on symba_pl' + end select + end associate + + return + end subroutine symba_util_copy_fill_pl + + module subroutine symba_util_copy_fill_tp(self, inserts, lfill_list) + !! author: David A. Minton + !! + !! Insert new SyMBA test particle structure into an old one. + !! This is the inverse of a fill operation. + !! + 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 + + associate(keeps => self) + select type(inserts) + class is (symba_tp) + keeps%nplenc(:) = unpack(keeps%nplenc(:), .not.lfill_list(:), keeps%nplenc(:)) + keeps%nplenc(:) = unpack(inserts%nplenc(:), lfill_list(:), keeps%nplenc(:)) + + keeps%levelg(:) = unpack(keeps%levelg(:), .not.lfill_list(:), keeps%levelg(:)) + keeps%levelg(:) = unpack(inserts%levelg(:), lfill_list(:), keeps%levelg(:)) + + keeps%levelm(:) = unpack(keeps%levelm(:), .not.lfill_list(:), keeps%levelm(:)) + keeps%levelm(:) = unpack(inserts%levelm(:), lfill_list(:), keeps%levelm(:)) + + call util_copy_fill_tp(keeps, inserts, lfill_list) + class default + write(*,*) 'Error! fill method called for incompatible return type on symba_tp' + end select + end associate + + return + end subroutine symba_util_copy_fill_tp + module subroutine symba_util_copy_pltpenc(self, source) !! author: David A. Minton !! diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 index ad3c111c4..3a4b1e9f6 100644 --- a/src/util/util_copy.f90 +++ b/src/util/util_copy.f90 @@ -311,7 +311,6 @@ module subroutine util_copy_spill_body(self, discards, lspill_list) if (allocated(keeps%omega)) discards%omega(:) = pack(keeps%omega(:), lspill_list(:)) if (allocated(keeps%capm)) discards%capm(:) = pack(keeps%capm(:), lspill_list(:)) - if (allocated(keeps%aobl)) then do i = 1, NDIM discards%aobl(i, :) = pack(keeps%aobl(i, :), lspill_list(:)) From d48cc7851ff9bb543a2309244d182a5320621d6e Mon Sep 17 00:00:00 2001 From: David Minton Date: Sat, 31 Jul 2021 19:44:06 -0400 Subject: [PATCH 05/42] Added spill methods to SyMBA --- src/modules/symba_classes.f90 | 18 +++++++ src/symba/symba_util.f90 | 95 +++++++++++++++++++++++++++++++++++ src/util/util_copy.f90 | 1 - 3 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 6a878520a..0080b1e07 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -95,6 +95,7 @@ module symba_classes procedure :: fill => symba_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: sort => symba_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure :: spill => symba_util_copy_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type symba_pl !******************************************************************************************************************************** @@ -113,6 +114,7 @@ module symba_classes procedure :: fill => symba_util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: sort => symba_util_sort_tp !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure :: spill => symba_util_copy_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type symba_tp !******************************************************************************************************************************** @@ -450,6 +452,22 @@ module subroutine symba_util_resize_pltpenc(self, nrequested) integer(I4B), intent(in) :: nrequested !! New size of list needed end subroutine symba_util_resize_pltpenc + module subroutine symba_util_copy_spill_pl(self, discards, lspill_list) + use swiftest_classes, only : swiftest_body + implicit none + 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 + end subroutine symba_util_copy_spill_pl + + module subroutine symba_util_copy_spill_tp(self, discards, lspill_list) + use swiftest_classes, only : swiftest_body + implicit none + 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 + end subroutine symba_util_copy_spill_tp + module subroutine symba_util_sort_pl(self, sortby, ascending) implicit none class(symba_pl), intent(inout) :: self !! SyMBA massive body object diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index b8dbbd49a..7d65665f8 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -140,6 +140,7 @@ module subroutine symba_util_copy_plplenc(self, source) return end subroutine symba_util_copy_plplenc + module subroutine symba_util_resize_pltpenc(self, nrequested) !! author: David A. Minton !! @@ -332,4 +333,98 @@ module subroutine symba_util_sort_rearrange_tp(self, ind) return end subroutine symba_util_sort_rearrange_tp + + module subroutine symba_util_copy_spill_pl(self, discards, lspill_list) + !! author: David A. Minton + !! + !! Move spilled (discarded) SyMBA massive body particle structure from active list to discard list + !! 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 + ! Internals + integer(I4B) :: i + + ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps + !> Spill all the common components + associate(keeps => self) + select type(discards) + class is (symba_pl) + discards%lcollision(:) = pack(keeps%lcollision(:), lspill_list(:)) + discards%lencounter(:) = pack(keeps%lencounter(:), lspill_list(:)) + discards%lmtiny(:) = pack(keeps%lmtiny(:), lspill_list(:)) + discards%nplenc(:) = pack(keeps%nplenc(:), lspill_list(:)) + discards%ntpenc(:) = pack(keeps%ntpenc(:), lspill_list(:)) + discards%levelg(:) = pack(keeps%levelg(:), lspill_list(:)) + discards%levelm(:) = pack(keeps%levelm(:), lspill_list(:)) + discards%isperi(:) = pack(keeps%isperi(:), lspill_list(:)) + discards%peri(:) = pack(keeps%peri(:), lspill_list(:)) + discards%atp(:) = pack(keeps%atp(:), lspill_list(:)) + discards%info(:) = pack(keeps%info(:), lspill_list(:)) + discards%kin(:) = pack(keeps%kin(:), lspill_list(:)) + + if (count(.not.lspill_list(:)) > 0) then + keeps%lcollision(:) = pack(keeps%lcollision(:), .not. lspill_list(:)) + keeps%lencounter(:) = pack(keeps%lencounter(:), .not. lspill_list(:)) + keeps%lmtiny(:) = pack(keeps%lmtiny(:), .not. lspill_list(:)) + keeps%nplenc(:) = pack(keeps%nplenc(:), .not. lspill_list(:)) + keeps%ntpenc(:) = pack(keeps%ntpenc(:), .not. lspill_list(:)) + keeps%levelg(:) = pack(keeps%levelg(:), .not. lspill_list(:)) + keeps%levelm(:) = pack(keeps%levelm(:), .not. lspill_list(:)) + keeps%isperi(:) = pack(keeps%isperi(:), .not. lspill_list(:)) + keeps%peri(:) = pack(keeps%peri(:), .not. lspill_list(:)) + keeps%atp(:) = pack(keeps%atp(:), .not. lspill_list(:)) + keeps%info(:) = pack(keeps%info(:), .not. lspill_list(:)) + keeps%kin(:) = pack(keeps%kin(:), .not. lspill_list(:)) + end if + + call util_copy_spill_pl(keeps, discards, lspill_list) + class default + write(*,*) 'Error! spill method called for incompatible return type on symba_pl' + end select + end associate + + return + end subroutine symba_util_copy_spill_pl + + + module subroutine symba_util_copy_spill_tp(self, discards, lspill_list) + !! author: David A. Minton + !! + !! Move spilled (discarded) SyMBA test particle structure from active list to discard list + !! 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 + ! Internals + integer(I4B) :: i + + ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps + !> Spill all the common components + associate(keeps => self) + select type(discards) + class is (symba_pl) + discards%nplenc(:) = pack(keeps%nplenc(:), lspill_list(:)) + discards%levelg(:) = pack(keeps%levelg(:), lspill_list(:)) + discards%levelm(:) = pack(keeps%levelm(:), lspill_list(:)) + + if (count(.not.lspill_list(:)) > 0) then + keeps%nplenc(:) = pack(keeps%nplenc(:), .not. lspill_list(:)) + keeps%levelg(:) = pack(keeps%levelg(:), .not. lspill_list(:)) + keeps%levelm(:) = pack(keeps%levelm(:), .not. lspill_list(:)) + end if + + call util_copy_spill_tp(keeps, discards, lspill_list) + class default + write(*,*) 'Error! spill method called for incompatible return type on symba_pl' + end select + end associate + + return + end subroutine symba_util_copy_spill_tp + end submodule s_symba_util \ No newline at end of file diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 index 3a4b1e9f6..261a490fd 100644 --- a/src/util/util_copy.f90 +++ b/src/util/util_copy.f90 @@ -378,7 +378,6 @@ module subroutine util_copy_spill_body(self, discards, lspill_list) allocate(discards%ldiscard(discards%nbody)) keeps%ldiscard = .false. discards%ldiscard = .true. - end associate return From ba91ddb83bb757caa5117f026129fec43df18e4b Mon Sep 17 00:00:00 2001 From: David Minton Date: Sun, 1 Aug 2021 15:25:04 -0400 Subject: [PATCH 06/42] Consolidated fill operations into a set of simple array subroutines that helps simplify the implementations a lot --- src/modules/swiftest_classes.f90 | 41 +++++- src/rmvs/rmvs_util.f90 | 18 +-- src/symba/symba_util.f90 | 50 ++----- src/util/util_copy.f90 | 243 ------------------------------- src/util/util_fill.f90 | 218 +++++++++++++++++++++++++++ src/whm/whm_util.f90 | 23 +-- 6 files changed, 284 insertions(+), 309 deletions(-) create mode 100644 src/util/util_fill.f90 diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 3711e5295..c8d05850f 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -85,7 +85,7 @@ module swiftest_classes !******************************************************************************************************************************** !> A concrete lass for the central body in a Swiftest simulation type, abstract, extends(swiftest_base) :: swiftest_cb - character(len=STRMAX) :: name !! Non-unique name + character(len=STRMAX) :: name !! Non-unique name 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) @@ -801,7 +801,46 @@ module subroutine util_copy_fill_tp(self, inserts, lfill_list) 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 util_copy_fill_tp + end interface + + interface util_fill + module subroutine util_fill_arr_char_string(keeps, inserts, lfill_list) + implicit none + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + character(len=STRMAX), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into keep + logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + end subroutine util_fill_arr_char_string + + module subroutine util_fill_arr_DP(keeps, inserts, lfill_list) + implicit none + real(DP), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + real(DP), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into keep + logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + end subroutine util_fill_arr_DP + + module subroutine util_fill_arr_DPvec(keeps, inserts, lfill_list) + implicit none + real(DP), dimension(:,:), allocatable, intent(inout) :: keeps !! Array of values to keep + real(DP), dimension(:,:), allocatable, intent(in) :: inserts !! Array of arrays to insert into keep + logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + end subroutine util_fill_arr_DPvec + module subroutine util_fill_arr_I4B(keeps, inserts, lfill_list) + implicit none + integer(I4B), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + integer(I4B), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into keep + logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + end subroutine util_fill_arr_I4B + + module subroutine util_fill_arr_logical(keeps, inserts, lfill_list) + implicit none + logical, dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + logical, dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into keep + logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + end subroutine util_fill_arr_logical + end interface + + interface module subroutine util_peri_tp(self, system, param) implicit none class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object diff --git a/src/rmvs/rmvs_util.f90 b/src/rmvs/rmvs_util.f90 index 863033c17..90949e593 100644 --- a/src/rmvs/rmvs_util.f90 +++ b/src/rmvs/rmvs_util.f90 @@ -20,9 +20,10 @@ module subroutine rmvs_util_copy_fill_pl(self, inserts, lfill_list) select type(inserts) class is (rmvs_pl) - keeps%nenc(:) = unpack(keeps%nenc(:), .not.lfill_list(:), keeps%nenc(:)) - keeps%nenc(:) = unpack(inserts%nenc(:), lfill_list(:), keeps%nenc(:)) - + call util_fill(keeps%nenc, inserts%nenc, lfill_list) + call util_fill(keeps%tpenc1P, inserts%tpenc1P, lfill_list) + call util_fill(keeps%plind, inserts%plind, lfill_list) + call whm_util_copy_fill_pl(keeps, inserts, lfill_list) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' @@ -49,14 +50,9 @@ module subroutine rmvs_util_copy_fill_tp(self, inserts, lfill_list) select type(inserts) class is (rmvs_tp) - keeps%lperi(:) = unpack(keeps%lperi(:), .not.lfill_list(:), keeps%lperi(:)) - keeps%lperi(:) = unpack(inserts%lperi(:), lfill_list(:), keeps%lperi(:)) - - keeps%plperP(:) = unpack(keeps%plperP(:), .not.lfill_list(:), keeps%plperP(:)) - keeps%plperP(:) = unpack(inserts%plperP(:), lfill_list(:), keeps%plperP(:)) - - keeps%plencP(:) = unpack(keeps%plencP(:), .not.lfill_list(:), keeps%plencP(:)) - keeps%plencP(:) = unpack(inserts%plencP(:), lfill_list(:), keeps%plencP(:)) + call util_fill(keeps%lperi, inserts%lperi, lfill_list) + call util_fill(keeps%plperP, inserts%plperP, lfill_list) + call util_fill(keeps%plencP, inserts%plencP, lfill_list) call util_copy_fill_tp(keeps, inserts, lfill_list) class default diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 7d65665f8..96781555c 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -17,35 +17,16 @@ module subroutine symba_util_copy_fill_pl(self, inserts, lfill_list) associate(keeps => self) select type(inserts) class is (symba_pl) - keeps%lcollision(:) = unpack(keeps%lcollision(:), .not.lfill_list(:), keeps%lcollision(:)) - keeps%lcollision(:) = unpack(inserts%lcollision(:), lfill_list(:), keeps%lcollision(:)) - - keeps%lencounter(:) = unpack(keeps%lencounter(:), .not.lfill_list(:), keeps%lencounter(:)) - keeps%lencounter(:) = unpack(inserts%lencounter(:), lfill_list(:), keeps%lencounter(:)) - - keeps%lmtiny(:) = unpack(keeps%lmtiny(:), .not.lfill_list(:), keeps%lmtiny(:)) - keeps%lmtiny(:) = unpack(inserts%lmtiny(:), lfill_list(:), keeps%lmtiny(:)) - - keeps%nplenc(:) = unpack(keeps%nplenc(:), .not.lfill_list(:), keeps%nplenc(:)) - keeps%nplenc(:) = unpack(inserts%nplenc(:), lfill_list(:), keeps%nplenc(:)) - - keeps%nplenc(:) = unpack(keeps%nplenc(:), .not.lfill_list(:), keeps%nplenc(:)) - keeps%ntpenc(:) = unpack(inserts%ntpenc(:), lfill_list(:), keeps%ntpenc(:)) - - keeps%levelg(:) = unpack(keeps%levelg(:), .not.lfill_list(:), keeps%levelg(:)) - keeps%levelg(:) = unpack(inserts%levelg(:), lfill_list(:), keeps%levelg(:)) - - keeps%levelm(:) = unpack(keeps%levelm(:), .not.lfill_list(:), keeps%levelm(:)) - keeps%levelm(:) = unpack(inserts%levelm(:), lfill_list(:), keeps%levelm(:)) - - keeps%isperi(:) = unpack(keeps%isperi(:), .not.lfill_list(:), keeps%isperi(:)) - keeps%isperi(:) = unpack(inserts%isperi(:), lfill_list(:), keeps%isperi(:)) - - keeps%peri(:) = unpack(keeps%peri(:), .not.lfill_list(:), keeps%peri(:)) - keeps%peri(:) = unpack(inserts%peri(:), lfill_list(:), keeps%peri(:)) - - keeps%atp(:) = unpack(keeps%atp(:), .not.lfill_list(:), keeps%atp(:)) - keeps%atp(:) = unpack(inserts%atp(:), lfill_list(:), keeps%atp(:)) + call util_fill(keeps%lcollision, inserts%lcollision, lfill_list) + call util_fill(keeps%lencounter, inserts%lencounter, lfill_list) + call util_fill(keeps%lmtiny, inserts%lmtiny, lfill_list) + call util_fill(keeps%nplenc, inserts%nplenc, lfill_list) + call util_fill(keeps%ntpenc, inserts%ntpenc, lfill_list) + call util_fill(keeps%levelg, inserts%levelg, lfill_list) + call util_fill(keeps%levelm, inserts%levelm, lfill_list) + call util_fill(keeps%isperi, inserts%isperi, lfill_list) + call util_fill(keeps%peri, inserts%peri, lfill_list) + call util_fill(keeps%atp, inserts%atp, lfill_list) keeps%kin(:) = unpack(keeps%kin(:), .not.lfill_list(:), keeps%kin(:)) keeps%kin(:) = unpack(inserts%kin(:), lfill_list(:), keeps%kin(:)) @@ -77,14 +58,9 @@ module subroutine symba_util_copy_fill_tp(self, inserts, lfill_list) associate(keeps => self) select type(inserts) class is (symba_tp) - keeps%nplenc(:) = unpack(keeps%nplenc(:), .not.lfill_list(:), keeps%nplenc(:)) - keeps%nplenc(:) = unpack(inserts%nplenc(:), lfill_list(:), keeps%nplenc(:)) - - keeps%levelg(:) = unpack(keeps%levelg(:), .not.lfill_list(:), keeps%levelg(:)) - keeps%levelg(:) = unpack(inserts%levelg(:), lfill_list(:), keeps%levelg(:)) - - keeps%levelm(:) = unpack(keeps%levelm(:), .not.lfill_list(:), keeps%levelm(:)) - keeps%levelm(:) = unpack(inserts%levelm(:), lfill_list(:), keeps%levelm(:)) + call util_fill(keeps%nplenc, inserts%nplenc, lfill_list) + call util_fill(keeps%levelg, inserts%levelg, lfill_list) + call util_fill(keeps%levelm, inserts%levelm, lfill_list) call util_copy_fill_tp(keeps, inserts, lfill_list) class default diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 index 261a490fd..60cf568b4 100644 --- a/src/util/util_copy.f90 +++ b/src/util/util_copy.f90 @@ -2,249 +2,6 @@ use swiftest contains - module subroutine util_copy_fill_body(self, inserts, lfill_list) - !! author: David A. Minton - !! - !! Insert new Swiftest generic particle structure into an old one. - !! This is the inverse of a fill operation. - implicit none - ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest generic 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 - ! internals - integer(I4B) :: i - - ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps - !> Spill all the common components - associate(keeps => self) - keeps%id(:) = unpack(keeps%id(:), .not.lfill_list(:), keeps%id(:)) - keeps%id(:) = unpack(inserts%id(:), lfill_list(:), keeps%id(:)) - - keeps%name(:) = unpack(keeps%name(:), .not.lfill_list(:), keeps%name(:)) - keeps%name(:) = unpack(inserts%name(:), lfill_list(:), keeps%name(:)) - - keeps%status(:) = unpack(keeps%status(:), .not.lfill_list(:), keeps%status(:)) - keeps%status(:) = unpack(inserts%status(:), lfill_list(:), keeps%status(:)) - - keeps%ldiscard(:) = unpack(keeps%ldiscard(:), .not.lfill_list(:), keeps%ldiscard(:)) - keeps%ldiscard(:) = unpack(inserts%ldiscard(:), lfill_list(:), keeps%ldiscard(:)) - - keeps%mu(:) = unpack(keeps%mu(:), .not.lfill_list(:), keeps%mu(:)) - keeps%mu(:) = unpack(inserts%mu(:), lfill_list(:), keeps%mu(:)) - - keeps%lmask(:) = unpack(keeps%lmask(:), .not.lfill_list(:), keeps%ldiscard(:)) - keeps%lmask(:) = unpack(inserts%lmask(:), lfill_list(:), keeps%ldiscard(:)) - - do i = 1, NDIM - keeps%xh(i, :) = unpack(keeps%xh(i, :), .not.lfill_list(:), keeps%xh(i, :)) - keeps%xh(i, :) = unpack(inserts%xh(i, :), lfill_list(:), keeps%xh(i, :)) - - keeps%vh(i, :) = unpack(keeps%vh(i, :), .not.lfill_list(:), keeps%vh(i, :)) - keeps%vh(i, :) = unpack(inserts%vh(i, :), lfill_list(:), keeps%vh(i, :)) - - keeps%xb(i, :) = unpack(keeps%xb(i, :), .not.lfill_list(:), keeps%xb(i, :)) - keeps%xb(i, :) = unpack(inserts%xb(i, :), lfill_list(:), keeps%xb(i, :)) - - keeps%vb(i, :) = unpack(keeps%vb(i, :), .not.lfill_list(:), keeps%vb(i, :)) - keeps%vb(i, :) = unpack(inserts%vb(i, :), lfill_list(:), keeps%vb(i, :)) - - keeps%ah(i, :) = unpack(keeps%ah(i, :), .not.lfill_list(:), keeps%ah(i, :)) - keeps%ah(i, :) = unpack(inserts%ah(i, :), lfill_list(:), keeps%ah(i, :)) - end do - - if (allocated(keeps%aobl)) then - do i = 1, NDIM - keeps%aobl(i, :) = unpack(keeps%aobl(i, :), .not.lfill_list(:), keeps%aobl(i, :)) - keeps%aobl(i, :) = unpack(inserts%aobl(i, :), lfill_list(:), keeps%aobl(i, :)) - end do - end if - - if (allocated(keeps%agr)) then - do i = 1, NDIM - keeps%agr(i, :) = unpack(keeps%agr(i, :), .not.lfill_list(:), keeps%agr(i, :)) - keeps%agr(i, :) = unpack(inserts%agr(i, :), lfill_list(:), keeps%agr(i, :)) - end do - end if - - if (allocated(keeps%atide)) then - do i = 1, NDIM - keeps%atide(i, :) = unpack(keeps%atide(i, :), .not.lfill_list(:), keeps%atide(i, :)) - keeps%atide(i, :) = unpack(inserts%atide(i, :), lfill_list(:), keeps%atide(i, :)) - end do - end if - - if (allocated(keeps%a)) then - keeps%a(:) = unpack(keeps%a(:), .not.lfill_list(:), keeps%a(:)) - keeps%a(:) = unpack(inserts%a(:), lfill_list(:), keeps%a(:)) - end if - - if (allocated(keeps%e)) then - keeps%e(:) = unpack(keeps%e(:), .not.lfill_list(:), keeps%e(:)) - keeps%e(:) = unpack(inserts%e(:), lfill_list(:), keeps%e(:)) - end if - - if (allocated(keeps%inc)) then - keeps%inc(:) = unpack(keeps%inc(:), .not.lfill_list(:), keeps%inc(:)) - keeps%inc(:) = unpack(inserts%inc(:), lfill_list(:), keeps%inc(:)) - end if - - if (allocated(keeps%capom)) then - keeps%capom(:) = unpack(keeps%capom(:),.not.lfill_list(:), keeps%capom(:)) - keeps%capom(:) = unpack(inserts%capom(:),lfill_list(:), keeps%capom(:)) - end if - - if (allocated(keeps%omega)) then - keeps%omega(:) = unpack(keeps%omega(:),.not.lfill_list(:), keeps%omega(:)) - keeps%omega(:) = unpack(inserts%omega(:),lfill_list(:), keeps%omega(:)) - end if - - if (allocated(keeps%capm)) then - keeps%capm(:) = unpack(keeps%capm(:), .not.lfill_list(:), keeps%capm(:)) - keeps%capm(:) = unpack(inserts%capm(:), lfill_list(:), keeps%capm(:)) - end if - - ! This is the base class, so will be the last to be called in the cascade. - keeps%nbody = size(keeps%id(:)) - end associate - - return - end subroutine util_copy_fill_body - - - module subroutine util_copy_fill_pl(self, inserts, lfill_list) - !! author: David A. Minton - !! - !! Insert new Swiftest massive body structure into an old one. - !! This is the inverse of a fill operation. - implicit none - ! Arguments - 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 - ! Internals - integer(I4B) :: i - - associate(keeps => self) - - select type (inserts) ! The standard requires us to select the type of both arguments in order to access all the components - class is (swiftest_pl) - !> Spill components specific to the massive body class - keeps%mass(:) = unpack(keeps%mass(:),.not.lfill_list(:), keeps%mass(:)) - keeps%mass(:) = unpack(inserts%mass(:),lfill_list(:), keeps%mass(:)) - - keeps%Gmass(:) = unpack(keeps%Gmass(:),.not.lfill_list(:), keeps%Gmass(:)) - keeps%Gmass(:) = unpack(inserts%Gmass(:),lfill_list(:), keeps%Gmass(:)) - - keeps%rhill(:) = unpack(keeps%rhill(:),.not.lfill_list(:), keeps%rhill(:)) - keeps%rhill(:) = unpack(inserts%rhill(:),lfill_list(:), keeps%rhill(:)) - - if (allocated(keeps%radius) .and. allocated(inserts%radius)) then - keeps%radius(:) = unpack(keeps%radius(:),.not.lfill_list(:), keeps%radius(:)) - keeps%radius(:) = unpack(inserts%radius(:),lfill_list(:), keeps%radius(:)) - end if - - if (allocated(keeps%density) .and. allocated(inserts%density)) then - keeps%density(:) = unpack(keeps%density(:),.not.lfill_list(:), keeps%density(:)) - keeps%density(:) = unpack(inserts%density(:),lfill_list(:), keeps%density(:)) - end if - - if (allocated(keeps%k2) .and. allocated(inserts%k2)) then - keeps%k2(:) = unpack(keeps%k2(:),.not.lfill_list(:), keeps%k2(:)) - keeps%k2(:) = unpack(inserts%k2(:),lfill_list(:), keeps%k2(:)) - end if - - if (allocated(keeps%Q) .and. allocated(inserts%Q)) then - keeps%Q(:) = unpack(keeps%Q(:),.not.lfill_list(:), keeps%Q(:)) - keeps%Q(:) = unpack(inserts%Q(:),lfill_list(:), keeps%Q(:)) - end if - - if (allocated(keeps%tlag) .and. allocated(inserts%tlag)) then - keeps%tlag(:) = unpack(keeps%tlag(:),.not.lfill_list(:), keeps%tlag(:)) - keeps%tlag(:) = unpack(inserts%tlag(:),lfill_list(:), keeps%tlag(:)) - end if - - if (allocated(keeps%xbeg) .and. allocated(inserts%xbeg)) then - do i = 1, NDIM - keeps%xbeg(i, :) = unpack(keeps%xbeg(i, :), .not.lfill_list(:), keeps%xbeg(i, :)) - keeps%xbeg(i, :) = unpack(inserts%xbeg(i, :), lfill_list(:), keeps%xbeg(i, :)) - end do - end if - - if (allocated(keeps%xend) .and. allocated(inserts%xend)) then - do i = 1, NDIM - keeps%xend(i, :) = unpack(keeps%xend(i, :), .not.lfill_list(:), keeps%xend(i, :)) - keeps%xend(i, :) = unpack(inserts%xend(i, :), lfill_list(:), keeps%xend(i, :)) - end do - end if - - if (allocated(keeps%vbeg) .and. allocated(inserts%vbeg)) then - do i = 1, NDIM - keeps%vbeg(i, :) = unpack(keeps%vbeg(i, :), .not.lfill_list(:), keeps%vbeg(i, :)) - keeps%vbeg(i, :) = unpack(inserts%vbeg(i, :), lfill_list(:), keeps%vbeg(i, :)) - end do - end if - - if (allocated(keeps%Ip) .and. allocated(inserts%Ip)) then - do i = 1, NDIM - keeps%Ip(i, :) = unpack(keeps%Ip(i, :), .not.lfill_list(:), keeps%Ip(i, :)) - keeps%Ip(i, :) = unpack(inserts%Ip(i, :), lfill_list(:), keeps%Ip(i, :)) - end do - end if - - if (allocated(keeps%rot) .and. allocated(inserts%rot)) then - do i = 1, NDIM - keeps%rot(i, :) = unpack(keeps%rot(i, :), .not.lfill_list(:), keeps%rot(i, :)) - keeps%rot(i, :) = unpack(inserts%rot(i, :), lfill_list(:), keeps%rot(i, :)) - end do - end if - - keeps%ldiscard(:) = unpack(inserts%ldiscard(:), lfill_list(:), keeps%ldiscard(:)) - - call util_copy_fill_body(keeps, inserts, lfill_list) - class default - write(*,*) 'Error! fill method called for incompatible return type on swiftest_pl' - end select - end associate - - return - end subroutine util_copy_fill_pl - - - module subroutine util_copy_fill_tp(self, inserts, lfill_list) - !! author: David A. Minton - !! - !! Insert new Swiftest test particle structure into an old one. - !! This is the inverse of a fill operation. - implicit none - ! Arguments - 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 - - associate(keeps => self) - select type(inserts) - class is (swiftest_tp) - !> Spill components specific to the test particle class - keeps%isperi(:) = unpack(keeps%isperi(:), .not.lfill_list(:), keeps%isperi(:)) - keeps%isperi(:) = unpack(inserts%isperi(:), lfill_list(:), keeps%isperi(:)) - - keeps%peri(:) = unpack(keeps%peri(:), .not.lfill_list(:), keeps%peri(:)) - keeps%peri(:) = unpack(inserts%peri(:), lfill_list(:), keeps%peri(:)) - - keeps%atp(:) = unpack(keeps%atp(:), .not.lfill_list(:), keeps%atp(:)) - keeps%atp(:) = unpack(inserts%atp(:), lfill_list(:), keeps%atp(:)) - - call util_copy_fill_body(keeps, inserts, lfill_list) - class default - write(*,*) 'Error! fill method called for incompatible return type on swiftest_tp' - end select - end associate - - return - end subroutine util_copy_fill_tp - - module subroutine util_copy_into_body(self, source, param, lsource_mask) !! author: David A. Minton !! diff --git a/src/util/util_fill.f90 b/src/util/util_fill.f90 new file mode 100644 index 000000000..47981c038 --- /dev/null +++ b/src/util/util_fill.f90 @@ -0,0 +1,218 @@ +submodule (swiftest_classes) s_util_fill + use swiftest +contains + + module subroutine 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 + 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 arrays 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 + + keeps(:) = unpack(keeps(:), .not.lfill_list(:), keeps(:)) + keeps(:) = unpack(inserts(:), lfill_list(:), keeps(:)) + + return + end subroutine util_fill_arr_char_string + + module subroutine 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 + implicit none + ! Arguments + real(DP), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + real(DP), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays 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 + + keeps(:) = unpack(keeps(:), .not.lfill_list(:), keeps(:)) + keeps(:) = unpack(inserts(:), lfill_list(:), keeps(:)) + + return + end subroutine util_fill_arr_DP + + module subroutine 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 + implicit none + ! Arguments + real(DP), dimension(:,:), allocatable, intent(inout) :: keeps !! Array of values to keep + real(DP), dimension(:,:), allocatable, intent(in) :: inserts !! Array of arrays to insert into keep + logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps + ! Internals + integer(I4B) :: i + + if (.not.allocated(keeps) .or. .not.allocated(inserts)) return + + do i = 1, NDIM + keeps(i,:) = unpack(keeps(i,:), .not.lfill_list(:), keeps(i,:)) + keeps(i,:) = unpack(inserts(i,:), lfill_list(:), keeps(i,:)) + end do + + return + end subroutine util_fill_arr_DPvec + + module subroutine 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 + implicit none + ! Arguments + integer(I4B), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + integer(I4B), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays 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 + + keeps(:) = unpack(keeps(:), .not.lfill_list(:), keeps(:)) + keeps(:) = unpack(inserts(:), lfill_list(:), keeps(:)) + + return + end subroutine util_fill_arr_I4B + + module subroutine 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 + implicit none + ! Arguments + logical, dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + logical, dimension(:), allocatable, intent(in) :: inserts !! Array of arrays 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 + + keeps(:) = unpack(keeps(:), .not.lfill_list(:), keeps(:)) + keeps(:) = unpack(inserts(:), lfill_list(:), keeps(:)) + + return + end subroutine util_fill_arr_logical + + + module subroutine util_copy_fill_body(self, inserts, lfill_list) + !! author: David A. Minton + !! + !! Insert new Swiftest generic particle structure into an old one. + !! This is the inverse of a spill operation. + implicit none + ! Arguments + class(swiftest_body), intent(inout) :: self !! Swiftest generic 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 + ! internals + integer(I4B) :: i + + ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps + !> Fill all the common components + associate(keeps => self) + call util_fill(keeps%id, inserts%id, lfill_list) + call util_fill(keeps%name, inserts%name, lfill_list) + call util_fill(keeps%status, inserts%status, lfill_list) + call util_fill(keeps%ldiscard, inserts%ldiscard, lfill_list) + call util_fill(keeps%mu, inserts%mu, lfill_list) + call util_fill(keeps%xh, inserts%xh, lfill_list) + call util_fill(keeps%vh, inserts%vh, lfill_list) + call util_fill(keeps%xb, inserts%xb, lfill_list) + call util_fill(keeps%vb, inserts%vb, lfill_list) + call util_fill(keeps%ah, inserts%ah, lfill_list) + call util_fill(keeps%aobl, inserts%aobl, lfill_list) + call util_fill(keeps%agr, inserts%agr, lfill_list) + call util_fill(keeps%atide, inserts%atide, lfill_list) + call util_fill(keeps%a, inserts%a, lfill_list) + call util_fill(keeps%e, inserts%e, lfill_list) + call util_fill(keeps%inc, inserts%inc, lfill_list) + call util_fill(keeps%capom, inserts%capom, lfill_list) + call util_fill(keeps%omega, inserts%omega, lfill_list) + call util_fill(keeps%capm, inserts%capm, lfill_list) + + ! This is the base class, so will be the last to be called in the cascade. + keeps%nbody = size(keeps%id(:)) + end associate + + return + end subroutine util_copy_fill_body + + + module subroutine util_copy_fill_pl(self, inserts, lfill_list) + !! author: David A. Minton + !! + !! Insert new Swiftest massive body structure into an old one. + !! This is the inverse of a spill operation. + implicit none + ! Arguments + 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 + ! Internals + integer(I4B) :: i + + associate(keeps => self) + + select type (inserts) ! The standard requires us to select the type of both arguments in order to access all the components + class is (swiftest_pl) + !> Fill components specific to the massive body class + call util_fill(keeps%mass, inserts%mass, lfill_list) + call util_fill(keeps%Gmass, inserts%Gmass, lfill_list) + call util_fill(keeps%rhill, inserts%rhill, lfill_list) + call util_fill(keeps%radius, inserts%radius, lfill_list) + call util_fill(keeps%density, inserts%density, lfill_list) + call util_fill(keeps%k2, inserts%k2, lfill_list) + call util_fill(keeps%Q, inserts%Q, lfill_list) + call util_fill(keeps%tlag, inserts%tlag, lfill_list) + call util_fill(keeps%xbeg, inserts%xbeg, lfill_list) + call util_fill(keeps%vbeg, inserts%vbeg, lfill_list) + call util_fill(keeps%Ip, inserts%Ip, lfill_list) + call util_fill(keeps%rot, inserts%rot, lfill_list) + + call util_copy_fill_body(keeps, inserts, lfill_list) + class default + write(*,*) 'Error! fill method called for incompatible return type on swiftest_pl' + end select + end associate + + return + end subroutine util_copy_fill_pl + + + module subroutine util_copy_fill_tp(self, inserts, lfill_list) + !! author: David A. Minton + !! + !! Insert new Swiftest test particle structure into an old one. + !! This is the inverse of a fill operation. + implicit none + ! Arguments + 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 + + associate(keeps => self) + select type(inserts) + class is (swiftest_tp) + !> Spill components specific to the test particle class + call util_fill(keeps%isperi, inserts%isperi, lfill_list) + call util_fill(keeps%peri, inserts%peri, lfill_list) + call util_fill(keeps%atp, inserts%atp, lfill_list) + + call util_copy_fill_body(keeps, inserts, lfill_list) + class default + write(*,*) 'Error! fill method called for incompatible return type on swiftest_tp' + end select + end associate + + return + end subroutine util_copy_fill_tp + +end submodule s_util_fill \ No newline at end of file diff --git a/src/whm/whm_util.f90 b/src/whm/whm_util.f90 index aaad01e84..ab5461f2d 100644 --- a/src/whm/whm_util.f90 +++ b/src/whm/whm_util.f90 @@ -63,23 +63,12 @@ module subroutine whm_util_copy_fill_pl(self, inserts, lfill_list) associate(keeps => self) select type(inserts) class is (whm_pl) - keeps%eta(:) = unpack(keeps%eta(:), .not.lfill_list(:), keeps%eta(:)) - keeps%eta(:) = unpack(inserts%eta(:), lfill_list(:), keeps%eta(:)) - - keeps%muj(:) = unpack(keeps%muj(:), .not.lfill_list(:), keeps%muj(:)) - keeps%muj(:) = unpack(inserts%muj(:), lfill_list(:), keeps%muj(:)) - - keeps%ir3j(:) = unpack(keeps%ir3j(:), .not.lfill_list(:), keeps%ir3j(:)) - keeps%ir3j(:) = unpack(inserts%ir3j(:), lfill_list(:), keeps%ir3j(:)) - - - do i = 1, NDIM - keeps%xj(i, :) = unpack(keeps%xj(i, :), .not.lfill_list(:), keeps%xj(i, :)) - keeps%xj(i, :) = unpack(inserts%xj(i, :), lfill_list(:), keeps%xj(i, :)) - - keeps%vj(i, :) = unpack(keeps%vj(i, :), .not.lfill_list(:), keeps%vj(i, :)) - keeps%vj(i, :) = unpack(inserts%vj(i, :), lfill_list(:), keeps%vj(i, :)) - end do + call util_fill(keeps%eta, inserts%eta, lfill_list) + call util_fill(keeps%muj, inserts%muj, lfill_list) + call util_fill(keeps%ir3j, inserts%ir3j, lfill_list) + call util_fill(keeps%xj, inserts%xj, lfill_list) + call util_fill(keeps%vj, inserts%vj, lfill_list) + call util_copy_fill_pl(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on whm_pl' From 0d2b22d6f0f926520fb4ae344610aa4db81de5b0 Mon Sep 17 00:00:00 2001 From: David Minton Date: Sun, 1 Aug 2021 20:32:31 -0400 Subject: [PATCH 07/42] Rewrote fill and spill methods with generic interface for simplicity --- src/discard/discard.f90 | 2 +- src/modules/rmvs_classes.f90 | 40 ++--- src/modules/swiftest_classes.f90 | 101 ++++++++---- src/modules/symba_classes.f90 | 38 ++--- src/modules/whm_classes.f90 | 17 +- src/rmvs/rmvs_util.f90 | 52 +++--- src/symba/symba_util.f90 | 83 +++++----- src/util/util_copy.f90 | 251 ---------------------------- src/util/util_fill.f90 | 27 ++-- src/util/util_spill.f90 | 269 +++++++++++++++++++++++++++++++ src/whm/whm_util.f90 | 36 ++--- 11 files changed, 481 insertions(+), 435 deletions(-) create mode 100644 src/util/util_spill.f90 diff --git a/src/discard/discard.f90 b/src/discard/discard.f90 index 292e52c38..0c84c9e88 100644 --- a/src/discard/discard.f90 +++ b/src/discard/discard.f90 @@ -69,7 +69,7 @@ module subroutine discard_tp(self, system, param) end if if (param%qmin >= 0.0_DP .and. ntp > 0) call discard_peri_tp(tp, system, param) if (param%lclose .and. ntp > 0) call discard_pl_tp(tp, system, param) - if (any(tp%ldiscard)) call tp%spill(system%tp_discards, tp%ldiscard) + if (any(tp%ldiscard)) call tp%spill(system%tp_discards, tp%ldiscard, ldestructive=.true.) end associate return diff --git a/src/modules/rmvs_classes.f90 b/src/modules/rmvs_classes.f90 index 64a0a5875..4c3bac64f 100644 --- a/src/modules/rmvs_classes.f90 +++ b/src/modules/rmvs_classes.f90 @@ -53,7 +53,7 @@ module rmvs_classes !! RMVS test particle class type, extends(whm_tp) :: rmvs_tp !! Note to developers: If you add componenets to this class, be sure to update methods and subroutines that traverse the - !! component list, such as rmvs_setup_tp and rmvs_util_copy_spill_tp + !! component list, such as rmvs_setup_tp and rmvs_util_spill_tp ! encounter steps) logical, dimension(:), allocatable :: lperi !! planetocentric pericenter passage flag (persistent for a full rmvs time step) over a full RMVS time step) integer(I4B), dimension(:), allocatable :: plperP !! index of planet associated with pericenter distance peri (persistent over a full RMVS time step) @@ -71,10 +71,10 @@ module rmvs_classes procedure :: accel => rmvs_kick_getacch_tp !! Calculates either the standard or modified version of the acceleration depending if the !! if the test particle is undergoing a close encounter or not procedure :: setup => rmvs_setup_tp !! Constructor method - Allocates space for number of particles - procedure :: fill => rmvs_util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => rmvs_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: sort => rmvs_util_sort_tp !! Sorts body arrays by a sortable componen procedure :: rearrange => rmvs_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => rmvs_util_copy_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => rmvs_util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type rmvs_tp !******************************************************************************************************************************** @@ -94,8 +94,8 @@ module rmvs_classes procedure :: setup => rmvs_setup_pl !! Constructor method - Allocates space for number of particles procedure :: sort => rmvs_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => rmvs_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: fill => rmvs_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) - procedure :: spill => rmvs_util_copy_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: fill => rmvs_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: spill => rmvs_util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type rmvs_pl interface @@ -154,21 +154,21 @@ module subroutine rmvs_setup_tp(self, n, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parametere end subroutine rmvs_setup_tp - module subroutine rmvs_util_copy_fill_pl(self, inserts, lfill_list) + module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none class(rmvs_pl), intent(inout) :: self !! RMVS massive 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 - end subroutine rmvs_util_copy_fill_pl + end subroutine rmvs_util_fill_pl - module subroutine rmvs_util_copy_fill_tp(self, inserts, lfill_list) + module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none class(rmvs_tp), intent(inout) :: self !! RMVS massive 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 - end subroutine rmvs_util_copy_fill_tp + end subroutine rmvs_util_fill_tp module subroutine rmvs_util_sort_pl(self, sortby, ascending) implicit none @@ -196,21 +196,23 @@ module subroutine rmvs_util_sort_rearrange_tp(self, ind) 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 rmvs_util_sort_rearrange_tp - module subroutine rmvs_util_copy_spill_pl(self, discards, lspill_list) + module subroutine rmvs_util_spill_pl(self, discards, lspill_list, ldestructive) use swiftest_classes, only : swiftest_body implicit none - class(rmvs_pl), intent(inout) :: self !! RMVS 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 - end subroutine rmvs_util_copy_spill_pl + class(rmvs_pl), intent(inout) :: self !! RMVS 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 rmvs_util_spill_pl - module subroutine rmvs_util_copy_spill_tp(self, discards, lspill_list) + module subroutine rmvs_util_spill_tp(self, discards, lspill_list, ldestructive) use swiftest_classes, only : swiftest_body implicit none - class(rmvs_tp), intent(inout) :: self !! RMVS 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 - end subroutine rmvs_util_copy_spill_tp + class(rmvs_tp), intent(inout) :: self !! RMVS 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 rmvs_util_spill_tp module subroutine rmvs_step_system(self, param, t, dt) use swiftest_classes, only : swiftest_parameters diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index c8d05850f..be342756e 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -145,7 +145,7 @@ module swiftest_classes real(DP), dimension(:), allocatable :: mu !! G * (Mcb + [m]) logical, dimension(:), allocatable :: lmask !! Logical mask used to select a subset of bodies when performing certain operations (drift, kick, accel, etc.) !! 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_copy_spill + !! component list, such as setup_body and util_spill contains procedure(abstract_discard_body), deferred :: discard procedure(abstract_kick_body), deferred :: kick @@ -166,12 +166,12 @@ module swiftest_classes procedure :: accel_user => user_kick_getacch_body !! Add user-supplied heliocentric accelerations to planets procedure :: append => util_append_body !! Appends elements from one structure to another procedure :: copy_into => util_copy_into_body !! Copies elements from one Swiftest body object to another. - procedure :: fill => util_copy_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => util_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => 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 => util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) procedure :: sort => util_sort_body !! Sorts body arrays by a sortable componen procedure :: rearrange => util_sort_rearrange_body !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => util_copy_spill_body !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: 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 !******************************************************************************************************************************** @@ -196,7 +196,7 @@ module swiftest_classes 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 !! 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_copy_spill_pl + !! 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 @@ -208,13 +208,13 @@ module swiftest_classes procedure :: accel_tides => tides_kick_getacch_pl !! Compute the accelerations of bodies due to tidal interactions with the central body procedure :: h2b => util_coord_h2b_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) procedure :: b2h => util_coord_b2h_pl !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) - procedure :: fill => util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: set_beg_end => util_set_beg_end_pl !! Sets the beginning and ending positions and velocities of planets. procedure :: set_mu => util_set_mu_pl !! Method used to construct the vectorized form of the central body mass procedure :: set_rhill => util_set_rhill !! Calculates the Hill's radii for each body procedure :: sort => util_sort_pl !! Sorts body arrays by a sortable component procedure :: rearrange => util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => util_copy_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: 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 !******************************************************************************************************************************** @@ -227,7 +227,7 @@ module swiftest_classes real(DP), dimension(:), allocatable :: peri !! Perihelion distance real(DP), dimension(:), allocatable :: atp !! Semimajor axis following perihelion passage !! 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_tp and util_copy_spill_tp + !! component list, such as setup_tp and util_spill_tp contains ! Test particle-specific concrete methods ! These are concrete because they are the same implemenation for all integrators @@ -237,12 +237,12 @@ module swiftest_classes procedure :: setup => setup_tp !! A base constructor that sets the number of bodies and procedure :: h2b => util_coord_h2b_tp !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) procedure :: b2h => util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) - procedure :: fill => util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: get_peri => util_peri_tp !! Determine system pericenter passages for test particles procedure :: set_mu => util_set_mu_tp !! Method used to construct the vectorized form of the central body mass procedure :: sort => util_sort_tp !! Sorts body arrays by a sortable component procedure :: rearrange => util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => util_copy_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: 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 !******************************************************************************************************************************** @@ -781,61 +781,61 @@ module subroutine util_exit(code) integer(I4B), intent(in) :: code !! Failure exit code end subroutine util_exit - module subroutine util_copy_fill_body(self, inserts, lfill_list) + module subroutine 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 - end subroutine util_copy_fill_body + end subroutine util_fill_body - module subroutine util_copy_fill_pl(self, inserts, lfill_list) + module subroutine 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 - end subroutine util_copy_fill_pl + end subroutine util_fill_pl - module subroutine util_copy_fill_tp(self, inserts, lfill_list) + module subroutine 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 - end subroutine util_copy_fill_tp + end subroutine util_fill_tp end interface interface util_fill module subroutine util_fill_arr_char_string(keeps, inserts, lfill_list) implicit none character(len=STRMAX), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - character(len=STRMAX), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 end subroutine util_fill_arr_char_string module subroutine util_fill_arr_DP(keeps, inserts, lfill_list) implicit none real(DP), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - real(DP), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 end subroutine util_fill_arr_DP module subroutine util_fill_arr_DPvec(keeps, inserts, lfill_list) implicit none real(DP), dimension(:,:), allocatable, intent(inout) :: keeps !! Array of values to keep - real(DP), dimension(:,:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 end subroutine util_fill_arr_DPvec module subroutine util_fill_arr_I4B(keeps, inserts, lfill_list) implicit none integer(I4B), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - integer(I4B), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 end subroutine util_fill_arr_I4B module subroutine util_fill_arr_logical(keeps, inserts, lfill_list) implicit none logical, dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - logical, dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 end subroutine util_fill_arr_logical end interface @@ -972,27 +972,74 @@ module subroutine util_sort_tp(self, sortby, ascending) 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_copy_spill_body(self, discards, lspill_list) + end interface + + interface util_spill + module subroutine util_spill_arr_char_string(keeps, discards, lspill_list, ldestructive) + implicit none + 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 discardss + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + end subroutine util_spill_arr_char_string + + module subroutine util_spill_arr_DP(keeps, discards, lspill_list, ldestructive) + implicit none + 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 discards + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + end subroutine util_spill_arr_DP + + module subroutine util_spill_arr_DPvec(keeps, discards, lspill_list, ldestructive) + implicit none + 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 + end subroutine util_spill_arr_DPvec + + module subroutine util_spill_arr_I4B(keeps, discards, lspill_list, ldestructive) + implicit none + 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 discardss + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + end subroutine util_spill_arr_I4B + + module subroutine util_spill_arr_logical(keeps, discards, lspill_list, ldestructive) + implicit none + 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 discardss + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + end subroutine util_spill_arr_logical + end interface + + interface + module subroutine 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 - end subroutine util_copy_spill_body + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + end subroutine util_spill_body - module subroutine util_copy_spill_pl(self, discards, lspill_list) + module subroutine 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 - end subroutine util_copy_spill_pl + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + end subroutine util_spill_pl - module subroutine util_copy_spill_tp(self, discards, lspill_list) + module subroutine 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 - end subroutine util_copy_spill_tp + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + end subroutine util_spill_tp module subroutine util_valid(pl, tp) implicit none diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 0080b1e07..f0cf9e00d 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -92,10 +92,10 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_pl !! Checks if massive bodies are going through close encounters with each other procedure :: accel => symba_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies procedure :: setup => symba_setup_pl !! Constructor method - Allocates space for number of particle - procedure :: fill => symba_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => symba_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: sort => symba_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => symba_util_copy_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => symba_util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type symba_pl !******************************************************************************************************************************** @@ -111,10 +111,10 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_tp !! Checks if any test particles are undergoing a close encounter with a massive body procedure :: accel => symba_kick_getacch_tp !! Compute heliocentric accelerations of test particles procedure :: setup => symba_setup_tp !! Constructor method - Allocates space for number of particle - procedure :: fill => symba_util_copy_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => symba_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: sort => symba_util_sort_tp !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => symba_util_copy_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => symba_util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type symba_tp !******************************************************************************************************************************** @@ -418,21 +418,21 @@ module subroutine symba_step_reset_system(self) class(symba_nbody_system), intent(inout) :: self !! SyMBA nbody system object end subroutine symba_step_reset_system - module subroutine symba_util_copy_fill_pl(self, inserts, lfill_list) + module subroutine symba_util_fill_pl(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none class(symba_pl), intent(inout) :: self !! SyMBA massive 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 - end subroutine symba_util_copy_fill_pl + end subroutine symba_util_fill_pl - module subroutine symba_util_copy_fill_tp(self, inserts, lfill_list) + module subroutine symba_util_fill_tp(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none 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 - end subroutine symba_util_copy_fill_tp + end subroutine symba_util_fill_tp module subroutine symba_util_copy_pltpenc(self, source) implicit none @@ -452,21 +452,23 @@ module subroutine symba_util_resize_pltpenc(self, nrequested) integer(I4B), intent(in) :: nrequested !! New size of list needed end subroutine symba_util_resize_pltpenc - module subroutine symba_util_copy_spill_pl(self, discards, lspill_list) + module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) use swiftest_classes, only : swiftest_body implicit none - 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 - end subroutine symba_util_copy_spill_pl + 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 the keeps array or not + end subroutine symba_util_spill_pl - module subroutine symba_util_copy_spill_tp(self, discards, lspill_list) + module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) use swiftest_classes, only : swiftest_body implicit none - 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 - end subroutine symba_util_copy_spill_tp + 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 the keeps array or not + end subroutine symba_util_spill_tp module subroutine symba_util_sort_pl(self, sortby, ascending) implicit none diff --git a/src/modules/whm_classes.f90 b/src/modules/whm_classes.f90 index 4dd7f646a..626c0a974 100644 --- a/src/modules/whm_classes.f90 +++ b/src/modules/whm_classes.f90 @@ -28,13 +28,13 @@ module whm_classes real(DP), dimension(:), allocatable :: muj !! Jacobi mu: GMcb * eta(i) / eta(i - 1) real(DP), dimension(:), allocatable :: ir3j !! Third term of heliocentric acceleration !! Note to developers: If you add componenets to this class, be sure to update methods and subroutines that traverse the - !! component list, such as whm_setup_pl and whm_util_copy_spill_pl + !! component list, such as whm_setup_pl and whm_util_spill_pl contains procedure :: h2j => whm_coord_h2j_pl !! Convert position and velcoity vectors from heliocentric to Jacobi coordinates procedure :: j2h => whm_coord_j2h_pl !! Convert position and velcoity vectors from Jacobi to helliocentric coordinates procedure :: vh2vj => whm_coord_vh2vj_pl !! Convert velocity vectors from heliocentric to Jacobi coordinates procedure :: drift => whm_drift_pl !! Loop through massive bodies and call Danby drift routine to jacobi coordinates - procedure :: fill => whm_util_copy_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => whm_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: accel => whm_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies procedure :: kick => whm_kick_vh_pl !! Kick heliocentric velocities of massive bodies procedure :: accel_gr => whm_gr_kick_getacch_pl !! Acceleration term arising from the post-Newtonian correction @@ -45,7 +45,7 @@ module whm_classes procedure :: sort => whm_util_sort_pl !! Sort a WHM massive body object in-place. procedure :: rearrange => whm_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods procedure :: step => whm_step_pl !! Steps the body forward one stepsize - procedure :: spill => whm_util_copy_spill_pl !!"Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => whm_util_spill_pl !!"Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type whm_pl !******************************************************************************************************************************** @@ -55,7 +55,7 @@ module whm_classes !! WHM test particle class type, extends(swiftest_tp) :: whm_tp !! Note to developers: If you add componenets to this class, be sure to update methods and subroutines that traverse the - !! component list, such as whm_util_copy_spill_tp + !! component list, such as whm_util_spill_tp contains procedure :: accel => whm_kick_getacch_tp !! Compute heliocentric accelerations of test particles procedure :: kick => whm_kick_vh_tp !! Kick heliocentric velocities of test particles @@ -106,13 +106,13 @@ module subroutine whm_drift_pl(self, system, param, dt) real(DP), intent(in) :: dt !! Stepsize end subroutine whm_drift_pl - module subroutine whm_util_copy_fill_pl(self, inserts, lfill_list) + module subroutine whm_util_fill_pl(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none class(whm_pl), intent(inout) :: self !! WHM massive 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 - end subroutine whm_util_copy_fill_pl + end subroutine whm_util_fill_pl !> Get heliocentric accelration of massive bodies module subroutine whm_kick_getacch_pl(self, system, param, t, lbeg) @@ -249,13 +249,14 @@ module subroutine whm_step_tp(self, system, param, t, dt) real(DP), intent(in) :: dt !! Stepsize end subroutine whm_step_tp - module subroutine whm_util_copy_spill_pl(self, discards, lspill_list) + module subroutine whm_util_spill_pl(self, discards, lspill_list, ldestructive) use swiftest_classes, only : swiftest_body implicit none class(whm_pl), intent(inout) :: self !! WHM 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 - end subroutine whm_util_copy_spill_pl + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not + end subroutine whm_util_spill_pl !> Steps the Swiftest nbody system forward in time one stepsize module subroutine whm_step_system(self, param, t, dt) diff --git a/src/rmvs/rmvs_util.f90 b/src/rmvs/rmvs_util.f90 index 90949e593..e9804bff6 100644 --- a/src/rmvs/rmvs_util.f90 +++ b/src/rmvs/rmvs_util.f90 @@ -2,7 +2,7 @@ use swiftest contains - module subroutine rmvs_util_copy_fill_pl(self, inserts, lfill_list) + module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new RMVS massive body structure into an old one. @@ -24,17 +24,17 @@ module subroutine rmvs_util_copy_fill_pl(self, inserts, lfill_list) call util_fill(keeps%tpenc1P, inserts%tpenc1P, lfill_list) call util_fill(keeps%plind, inserts%plind, lfill_list) - call whm_util_copy_fill_pl(keeps, inserts, lfill_list) + call whm_util_fill_pl(keeps, inserts, lfill_list) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' end select end associate return - end subroutine rmvs_util_copy_fill_pl + end subroutine rmvs_util_fill_pl - module subroutine rmvs_util_copy_fill_tp(self, inserts, lfill_list) + module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new RMVS test particle structure into an old one. @@ -54,14 +54,14 @@ module subroutine rmvs_util_copy_fill_tp(self, inserts, lfill_list) call util_fill(keeps%plperP, inserts%plperP, lfill_list) call util_fill(keeps%plencP, inserts%plencP, lfill_list) - call util_copy_fill_tp(keeps, inserts, lfill_list) + call util_fill_tp(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on rmvs_tp' end select end associate return - end subroutine rmvs_util_copy_fill_tp + end subroutine rmvs_util_fill_tp module subroutine rmvs_util_sort_pl(self, sortby, ascending) !! author: David A. Minton @@ -202,7 +202,7 @@ module subroutine rmvs_util_sort_rearrange_tp(self, ind) end subroutine rmvs_util_sort_rearrange_tp - module subroutine rmvs_util_copy_spill_pl(self, discards, lspill_list) + module subroutine rmvs_util_spill_pl(self, discards, lspill_list, ldestructive) !! author: David A. Minton !! !! Move spilled (discarded) RMVS test particle structure from active list to discard list @@ -210,30 +210,30 @@ module subroutine rmvs_util_copy_spill_pl(self, discards, lspill_list) !! Adapted from David E. Kaufmann's Swifter routine discard_discard_spill.f90 implicit none ! Arguments - class(rmvs_pl), intent(inout) :: self !! RMVS massive body 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 + class(rmvs_pl), intent(inout) :: self !! RMVS massive body 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 ! Internals integer(I4B) :: i associate(keeps => self) select type(discards) class is (rmvs_pl) - discards%nenc(:) = pack(keeps%nenc(:), lspill_list(:)) - if (count(.not.lspill_list(:)) > 0) then - keeps%nenc(:) = pack(keeps%nenc(:), .not. lspill_list(:)) - end if - call whm_util_copy_spill_pl(keeps, discards, lspill_list) + call util_spill(keeps%nenc, discards%nenc, lspill_list, ldestructive) + call util_spill(keeps%tpenc1P, discards%tpenc1P, lspill_list, ldestructive) + call util_spill(keeps%plind, discards%plind, lspill_list, ldestructive) + call whm_util_spill_pl(keeps, discards, lspill_list, ldestructive) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' end select end associate return - end subroutine rmvs_util_copy_spill_pl + end subroutine rmvs_util_spill_pl - module subroutine rmvs_util_copy_spill_tp(self, discards, lspill_list) + module subroutine rmvs_util_spill_tp(self, discards, lspill_list, ldestructive) !! author: David A. Minton !! !! Move spilled (discarded) RMVS test particle structure from active list to discard list @@ -244,28 +244,24 @@ module subroutine rmvs_util_copy_spill_tp(self, discards, lspill_list) class(rmvs_tp), intent(inout) :: self !! RMVS 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 ! Internals integer(I4B) :: i associate(keeps => self) select type(discards) class is (rmvs_tp) - discards%lperi(:) = pack(keeps%lperi(:), lspill_list(:)) - discards%plperP(:) = pack(keeps%plperP(:), lspill_list(:)) - discards%plencP(:) = pack(keeps%plencP(:), lspill_list(:)) - if (count(.not.lspill_list(:)) > 0) then - keeps%lperi(:) = pack(keeps%lperi(:), .not. lspill_list(:)) - keeps%plperP(:) = pack(keeps%plperP(:), .not. lspill_list(:)) - keeps%plencP(:) = pack(keeps%plencP(:), .not. lspill_list(:)) - end if - - call util_copy_spill_tp(keeps, discards, lspill_list) + call util_spill(keeps%lperi, discards%lperi, lspill_list, ldestructive) + call util_spill(keeps%plperP, discards%plperP, lspill_list, ldestructive) + call util_spill(keeps%plencP, discards%plencP, lspill_list, ldestructive) + + call util_spill_tp(keeps, discards, lspill_list, ldestructive) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_tp' end select end associate return - end subroutine rmvs_util_copy_spill_tp + end subroutine rmvs_util_spill_tp end submodule s_rmvs_util diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 96781555c..8c9a0a1d7 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -2,7 +2,7 @@ use swiftest contains - module subroutine symba_util_copy_fill_pl(self, inserts, lfill_list) + module subroutine symba_util_fill_pl(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new SyMBA test particle structure into an old one. @@ -34,16 +34,16 @@ module subroutine symba_util_copy_fill_pl(self, inserts, lfill_list) keeps%info(:) = unpack(keeps%info(:), .not.lfill_list(:), keeps%info(:)) keeps%info(:) = unpack(inserts%info(:), lfill_list(:), keeps%info(:)) - call util_copy_fill_pl(keeps, inserts, lfill_list) + call util_fill_pl(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on symba_pl' end select end associate return - end subroutine symba_util_copy_fill_pl + end subroutine symba_util_fill_pl - module subroutine symba_util_copy_fill_tp(self, inserts, lfill_list) + module subroutine symba_util_fill_tp(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new SyMBA test particle structure into an old one. @@ -62,14 +62,14 @@ module subroutine symba_util_copy_fill_tp(self, inserts, lfill_list) call util_fill(keeps%levelg, inserts%levelg, lfill_list) call util_fill(keeps%levelm, inserts%levelm, lfill_list) - call util_copy_fill_tp(keeps, inserts, lfill_list) + call util_fill_tp(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on symba_tp' end select end associate return - end subroutine symba_util_copy_fill_tp + end subroutine symba_util_fill_tp module subroutine symba_util_copy_pltpenc(self, source) !! author: David A. Minton @@ -310,7 +310,7 @@ module subroutine symba_util_sort_rearrange_tp(self, ind) end subroutine symba_util_sort_rearrange_tp - module subroutine symba_util_copy_spill_pl(self, discards, lspill_list) + module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) !! author: David A. Minton !! !! Move spilled (discarded) SyMBA massive body particle structure from active list to discard list @@ -320,6 +320,7 @@ module subroutine symba_util_copy_spill_pl(self, discards, lspill_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 ! Internals integer(I4B) :: i @@ -328,54 +329,48 @@ module subroutine symba_util_copy_spill_pl(self, discards, lspill_list) associate(keeps => self) select type(discards) class is (symba_pl) - discards%lcollision(:) = pack(keeps%lcollision(:), lspill_list(:)) - discards%lencounter(:) = pack(keeps%lencounter(:), lspill_list(:)) - discards%lmtiny(:) = pack(keeps%lmtiny(:), lspill_list(:)) - discards%nplenc(:) = pack(keeps%nplenc(:), lspill_list(:)) - discards%ntpenc(:) = pack(keeps%ntpenc(:), lspill_list(:)) - discards%levelg(:) = pack(keeps%levelg(:), lspill_list(:)) - discards%levelm(:) = pack(keeps%levelm(:), lspill_list(:)) - discards%isperi(:) = pack(keeps%isperi(:), lspill_list(:)) - discards%peri(:) = pack(keeps%peri(:), lspill_list(:)) - discards%atp(:) = pack(keeps%atp(:), lspill_list(:)) + + call util_spill(keeps%lcollision, discards%lcollision, lspill_list, ldestructive) + call util_spill(keeps%lencounter, discards%lencounter, lspill_list, ldestructive) + call util_spill(keeps%lmtiny, discards%lmtiny, lspill_list, ldestructive) + call util_spill(keeps%nplenc, discards%nplenc, lspill_list, ldestructive) + call util_spill(keeps%ntpenc, discards%ntpenc, lspill_list, ldestructive) + call util_spill(keeps%levelg, discards%levelg, lspill_list, ldestructive) + call util_spill(keeps%levelm, discards%levelm, lspill_list, ldestructive) + call util_spill(keeps%isperi, discards%isperi, lspill_list, ldestructive) + call util_spill(keeps%peri, discards%peri, lspill_list, ldestructive) + call util_spill(keeps%atp, discards%atp, lspill_list, ldestructive) discards%info(:) = pack(keeps%info(:), lspill_list(:)) discards%kin(:) = pack(keeps%kin(:), lspill_list(:)) - if (count(.not.lspill_list(:)) > 0) then - keeps%lcollision(:) = pack(keeps%lcollision(:), .not. lspill_list(:)) - keeps%lencounter(:) = pack(keeps%lencounter(:), .not. lspill_list(:)) - keeps%lmtiny(:) = pack(keeps%lmtiny(:), .not. lspill_list(:)) - keeps%nplenc(:) = pack(keeps%nplenc(:), .not. lspill_list(:)) - keeps%ntpenc(:) = pack(keeps%ntpenc(:), .not. lspill_list(:)) - keeps%levelg(:) = pack(keeps%levelg(:), .not. lspill_list(:)) - keeps%levelm(:) = pack(keeps%levelm(:), .not. lspill_list(:)) - keeps%isperi(:) = pack(keeps%isperi(:), .not. lspill_list(:)) - keeps%peri(:) = pack(keeps%peri(:), .not. lspill_list(:)) - keeps%atp(:) = pack(keeps%atp(:), .not. lspill_list(:)) - keeps%info(:) = pack(keeps%info(:), .not. lspill_list(:)) - keeps%kin(:) = pack(keeps%kin(:), .not. lspill_list(:)) + if (ldestructive) then + if (count(.not.lspill_list(:)) > 0) then + keeps%info(:) = pack(keeps%info(:), .not. lspill_list(:)) + keeps%kin(:) = pack(keeps%kin(:), .not. lspill_list(:)) + end if end if - call util_copy_spill_pl(keeps, discards, lspill_list) + call util_spill_pl(keeps, discards, lspill_list, ldestructive) class default write(*,*) 'Error! spill method called for incompatible return type on symba_pl' end select end associate return - end subroutine symba_util_copy_spill_pl + end subroutine symba_util_spill_pl - module subroutine symba_util_copy_spill_tp(self, discards, lspill_list) + module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) !! author: David A. Minton !! !! Move spilled (discarded) SyMBA test particle structure from active list to discard list !! 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 + 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 ! Internals integer(I4B) :: i @@ -384,23 +379,17 @@ module subroutine symba_util_copy_spill_tp(self, discards, lspill_list) associate(keeps => self) select type(discards) class is (symba_pl) - discards%nplenc(:) = pack(keeps%nplenc(:), lspill_list(:)) - discards%levelg(:) = pack(keeps%levelg(:), lspill_list(:)) - discards%levelm(:) = pack(keeps%levelm(:), lspill_list(:)) - - if (count(.not.lspill_list(:)) > 0) then - keeps%nplenc(:) = pack(keeps%nplenc(:), .not. lspill_list(:)) - keeps%levelg(:) = pack(keeps%levelg(:), .not. lspill_list(:)) - keeps%levelm(:) = pack(keeps%levelm(:), .not. lspill_list(:)) - end if + call util_spill(keeps%nplenc, discards%nplenc, lspill_list, ldestructive) + call util_spill(keeps%levelg, discards%levelg, lspill_list, ldestructive) + call util_spill(keeps%levelm, discards%levelm, lspill_list, ldestructive) - call util_copy_spill_tp(keeps, discards, lspill_list) + call util_spill_tp(keeps, discards, lspill_list, ldestructive) class default write(*,*) 'Error! spill method called for incompatible return type on symba_pl' end select end associate return - end subroutine symba_util_copy_spill_tp + end subroutine symba_util_spill_tp end submodule s_symba_util \ No newline at end of file diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 index 60cf568b4..bc8cdcf43 100644 --- a/src/util/util_copy.f90 +++ b/src/util/util_copy.f90 @@ -32,255 +32,4 @@ module subroutine util_copy_into_body(self, source, param, lsource_mask) return end subroutine util_copy_into_body - - module subroutine util_copy_spill_body(self, discards, lspill_list) - !! author: David A. Minton - !! - !! Move spilled (discarded) Swiftest generic particle structure from active list to discard list - !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 - implicit none - ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest generic 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 - ! Internals - integer(I4B) :: i - - ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps - !> Spill all the common components - associate(keeps => self) - discards%id(:) = pack(keeps%id(:), lspill_list(:)) - discards%name(:) = pack(keeps%name(:), lspill_list(:)) - discards%status(:) = pack(keeps%status(:), lspill_list(:)) - discards%mu(:) = pack(keeps%mu(:), lspill_list(:)) - discards%lmask(:) = pack(keeps%lmask(:), lspill_list(:)) - do i = 1, NDIM - discards%xh(i, :) = pack(keeps%xh(i, :), lspill_list(:)) - discards%vh(i, :) = pack(keeps%vh(i, :), lspill_list(:)) - discards%xb(i, :) = pack(keeps%xb(i, :), lspill_list(:)) - discards%vb(i, :) = pack(keeps%vb(i, :), lspill_list(:)) - discards%ah(i, :) = pack(keeps%ah(i, :), lspill_list(:)) - end do - - if (allocated(keeps%a)) discards%a(:) = pack(keeps%a(:), lspill_list(:)) - if (allocated(keeps%e)) discards%e(:) = pack(keeps%e(:), lspill_list(:)) - if (allocated(keeps%capom)) discards%capom(:) = pack(keeps%capom(:), lspill_list(:)) - if (allocated(keeps%omega)) discards%omega(:) = pack(keeps%omega(:), lspill_list(:)) - if (allocated(keeps%capm)) discards%capm(:) = pack(keeps%capm(:), lspill_list(:)) - - if (allocated(keeps%aobl)) then - do i = 1, NDIM - discards%aobl(i, :) = pack(keeps%aobl(i, :), lspill_list(:)) - end do - end if - if (allocated(keeps%agr)) then - do i = 1, NDIM - discards%agr(i, :) = pack(keeps%agr(i, :), lspill_list(:)) - end do - end if - if (allocated(keeps%atide)) then - do i = 1, NDIM - discards%atide(i, :) = pack(keeps%atide(i, :), lspill_list(:)) - end do - end if - - if (count(.not.lspill_list(:)) > 0) then - keeps%id(:) = pack(keeps%id(:), .not. lspill_list(:)) - keeps%name(:) = pack(keeps%name(:), .not. lspill_list(:)) - keeps%status(:) = pack(keeps%status(:), .not. lspill_list(:)) - keeps%mu(:) = pack(keeps%mu(:), .not. lspill_list(:)) - keeps%lmask(:) = pack(keeps%lmask(:), .not. lspill_list(:)) - - do i = 1, NDIM - keeps%xh(i, :) = pack(keeps%xh(i, :), .not. lspill_list(:)) - keeps%vh(i, :) = pack(keeps%vh(i, :), .not. lspill_list(:)) - keeps%xb(i, :) = pack(keeps%xb(i, :), .not. lspill_list(:)) - keeps%vb(i, :) = pack(keeps%vb(i, :), .not. lspill_list(:)) - keeps%ah(i, :) = pack(keeps%ah(i, :), .not. lspill_list(:)) - end do - - if (allocated(keeps%a)) keeps%a(:) = pack(keeps%a(:), .not. lspill_list(:)) - if (allocated(keeps%e)) keeps%e(:) = pack(keeps%e(:), .not. lspill_list(:)) - if (allocated(keeps%inc)) keeps%inc(:) = pack(keeps%inc(:), .not. lspill_list(:)) - if (allocated(keeps%capom)) keeps%capom(:) = pack(keeps%capom(:), .not. lspill_list(:)) - if (allocated(keeps%omega)) keeps%omega(:) = pack(keeps%omega(:), .not. lspill_list(:)) - if (allocated(keeps%capm)) keeps%capm(:) = pack(keeps%capm(:), .not. lspill_list(:)) - - if (allocated(keeps%aobl)) then - do i = 1, NDIM - keeps%aobl(i, :) = pack(keeps%aobl(i, :), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%agr)) then - do i = 1, NDIM - keeps%agr(i, :) = pack(keeps%agr(i, :), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%atide)) then - do i = 1, NDIM - keeps%atide(i, :) = pack(keeps%atide(i, :), .not. lspill_list(:)) - end do - end if - - end if - ! This is the base class, so will be the last to be called in the cascade. - ! Therefore we need to set the nbody values for both the keeps and discareds - discards%nbody = count(lspill_list(:)) - keeps%nbody = count(.not.lspill_list(:)) - if (allocated(keeps%ldiscard)) deallocate(keeps%ldiscard) - if (allocated(discards%ldiscard)) deallocate(discards%ldiscard) - allocate(keeps%ldiscard(keeps%nbody)) - allocate(discards%ldiscard(discards%nbody)) - keeps%ldiscard = .false. - discards%ldiscard = .true. - end associate - - return - end subroutine util_copy_spill_body - - - module subroutine util_copy_spill_pl(self, discards, lspill_list) - !! author: David A. Minton - !! - !! Move spilled (discarded) Swiftest massive body structure from active list to discard list - !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 - implicit none - ! Arguments - 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 - ! Internals - integer(I4B) :: i - - associate(keeps => self) - - select type (discards) ! The standard requires us to select the type of both arguments in order to access all the components - class is (swiftest_pl) - !> Spill components specific to the massive body class - discards%mass(:) = pack(keeps%mass(:), lspill_list(:)) - discards%Gmass(:) = pack(keeps%Gmass(:), lspill_list(:)) - discards%rhill(:) = pack(keeps%rhill(:), lspill_list(:)) - - if (allocated(keeps%radius)) discards%radius(:) = pack(keeps%radius(:), lspill_list(:)) - if (allocated(keeps%density)) discards%density(:) = pack(keeps%density(:), lspill_list(:)) - if (allocated(keeps%k2)) discards%k2(:) = pack(keeps%k2(:), lspill_list(:)) - if (allocated(keeps%Q)) discards%Q(:) = pack(keeps%Q(:), lspill_list(:)) - if (allocated(keeps%tlag)) discards%tlag(:) = pack(keeps%tlag(:), lspill_list(:)) - - if (allocated(keeps%xbeg)) then - do i = 1, NDIM - discards%xbeg(i, :) = pack(keeps%xbeg(i, :), lspill_list(:)) - end do - end if - - if (allocated(keeps%xend)) then - do i = 1, NDIM - discards%xend(i, :) = pack(keeps%xend(i, :), lspill_list(:)) - end do - end if - - if (allocated(keeps%vbeg)) then - do i = 1, NDIM - discards%vbeg(i, :) = pack(keeps%vbeg(i, :), lspill_list(:)) - end do - end if - - if (allocated(keeps%Ip)) then - do i = 1, NDIM - discards%Ip(i, :) = pack(keeps%Ip(i, :), lspill_list(:)) - end do - end if - - if (allocated(keeps%rot)) then - do i = 1, NDIM - discards%rot(i, :) = pack(keeps%rot(i, :), lspill_list(:)) - end do - end if - - if (count(.not.lspill_list(:)) > 0) then - keeps%mass(:) = pack(keeps%mass(:), .not. lspill_list(:)) - keeps%Gmass(:) = pack(keeps%Gmass(:), .not. lspill_list(:)) - keeps%rhill(:) = pack(keeps%rhill(:), .not. lspill_list(:)) - if (allocated(keeps%radius)) keeps%radius(:) = pack(keeps%radius(:), .not. lspill_list(:)) - if (allocated(keeps%density)) keeps%density(:) = pack(keeps%density(:), .not. lspill_list(:)) - if (allocated(keeps%k2)) keeps%k2(:) = pack(keeps%k2(:), .not. lspill_list(:)) - if (allocated(keeps%Q)) keeps%Q(:) = pack(keeps%Q(:), .not. lspill_list(:)) - if (allocated(keeps%tlag)) keeps%tlag(:) = pack(keeps%tlag(:), .not. lspill_list(:)) - - if (allocated(keeps%xbeg)) then - do i = 1, NDIM - keeps%xbeg(i,:) = pack(keeps%xbeg(i,:), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%xend)) then - do i = 1, NDIM - keeps%xend(i,:) = pack(keeps%xend(i,:), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%vbeg)) then - do i = 1, NDIM - keeps%vbeg(i,:) = pack(keeps%vbeg(i,:), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%Ip)) then - do i = 1, NDIM - keeps%Ip(i,:) = pack(keeps%Ip(i,:), .not. lspill_list(:)) - end do - end if - - if (allocated(keeps%rot)) then - do i = 1, NDIM - keeps%rot(i,:) = pack(keeps%rot(i,:), .not. lspill_list(:)) - end do - end if - - end if - - call util_copy_spill_body(keeps, discards, lspill_list) - class default - write(*,*) 'Error! spill method called for incompatible return type on swiftest_pl' - end select - end associate - - return - end subroutine util_copy_spill_pl - - - module subroutine util_copy_spill_tp(self, discards, lspill_list) - !! author: David A. Minton - !! - !! Move spilled (discarded) Swiftest test particle structure from active list to discard list - !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 - implicit none - ! Arguments - 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 discardse - - associate(keeps => self, ntp => self%nbody) - select type(discards) - class is (swiftest_tp) - !> Spill components specific to the test particle class - discards%isperi(:) = pack(keeps%isperi(:), lspill_list(:)) - discards%peri(:) = pack(keeps%peri(:), lspill_list(:)) - discards%atp(:) = pack(keeps%atp(:), lspill_list(:)) - if (count(.not.lspill_list(:)) > 0) then - keeps%atp(:) = pack(keeps%atp(:), .not. lspill_list(:)) - keeps%peri(:) = pack(keeps%peri(:), .not. lspill_list(:)) - keeps%isperi(:) = pack(keeps%isperi(:), .not. lspill_list(:)) - end if - call util_copy_spill_body(keeps, discards, lspill_list) - class default - write(*,*) 'Error! spill method called for incompatible return type on swiftest_tp' - end select - end associate - - return - end subroutine util_copy_spill_tp - end submodule s_util_copy \ No newline at end of file diff --git a/src/util/util_fill.f90 b/src/util/util_fill.f90 index 47981c038..4a5a70311 100644 --- a/src/util/util_fill.f90 +++ b/src/util/util_fill.f90 @@ -10,7 +10,7 @@ module subroutine util_fill_arr_char_string(keeps, inserts, lfill_list) 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 arrays to insert into 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 @@ -29,7 +29,7 @@ module subroutine util_fill_arr_DP(keeps, inserts, lfill_list) implicit none ! Arguments real(DP), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - real(DP), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 @@ -48,7 +48,7 @@ module subroutine util_fill_arr_DPvec(keeps, inserts, lfill_list) implicit none ! Arguments real(DP), dimension(:,:), allocatable, intent(inout) :: keeps !! Array of values to keep - real(DP), dimension(:,:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 @@ -71,7 +71,7 @@ module subroutine util_fill_arr_I4B(keeps, inserts, lfill_list) implicit none ! Arguments integer(I4B), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - integer(I4B), dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 @@ -90,7 +90,7 @@ module subroutine util_fill_arr_logical(keeps, inserts, lfill_list) implicit none ! Arguments logical, dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep - logical, dimension(:), allocatable, intent(in) :: inserts !! Array of arrays to insert into 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 @@ -102,7 +102,7 @@ module subroutine util_fill_arr_logical(keeps, inserts, lfill_list) end subroutine util_fill_arr_logical - module subroutine util_copy_fill_body(self, inserts, lfill_list) + module subroutine util_fill_body(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new Swiftest generic particle structure into an old one. @@ -122,6 +122,7 @@ module subroutine util_copy_fill_body(self, inserts, lfill_list) call util_fill(keeps%name, inserts%name, lfill_list) call util_fill(keeps%status, inserts%status, lfill_list) call util_fill(keeps%ldiscard, inserts%ldiscard, lfill_list) + call util_fill(keeps%lmask, inserts%lmask, lfill_list) call util_fill(keeps%mu, inserts%mu, lfill_list) call util_fill(keeps%xh, inserts%xh, lfill_list) call util_fill(keeps%vh, inserts%vh, lfill_list) @@ -143,10 +144,10 @@ module subroutine util_copy_fill_body(self, inserts, lfill_list) end associate return - end subroutine util_copy_fill_body + end subroutine util_fill_body - module subroutine util_copy_fill_pl(self, inserts, lfill_list) + module subroutine util_fill_pl(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new Swiftest massive body structure into an old one. @@ -177,17 +178,17 @@ module subroutine util_copy_fill_pl(self, inserts, lfill_list) call util_fill(keeps%Ip, inserts%Ip, lfill_list) call util_fill(keeps%rot, inserts%rot, lfill_list) - call util_copy_fill_body(keeps, inserts, lfill_list) + call util_fill_body(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on swiftest_pl' end select end associate return - end subroutine util_copy_fill_pl + end subroutine util_fill_pl - module subroutine util_copy_fill_tp(self, inserts, lfill_list) + module subroutine util_fill_tp(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new Swiftest test particle structure into an old one. @@ -206,13 +207,13 @@ module subroutine util_copy_fill_tp(self, inserts, lfill_list) call util_fill(keeps%peri, inserts%peri, lfill_list) call util_fill(keeps%atp, inserts%atp, lfill_list) - call util_copy_fill_body(keeps, inserts, lfill_list) + call util_fill_body(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on swiftest_tp' end select end associate return - end subroutine util_copy_fill_tp + end subroutine util_fill_tp end submodule s_util_fill \ No newline at end of file diff --git a/src/util/util_spill.f90 b/src/util/util_spill.f90 new file mode 100644 index 000000000..5f942854a --- /dev/null +++ b/src/util/util_spill.f90 @@ -0,0 +1,269 @@ +submodule (swiftest_classes) s_util_spill + use swiftest +contains + + module subroutine 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 + 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 + + if (.not.allocated(keeps) .or. count(lspill_list(:)) == 0) return + if (.not.allocated(discards)) allocate(discards(count(lspill_list(:)))) + + discards(:) = pack(keeps(:), lspill_list(:)) + if (ldestructive) then + if (count(.not.lspill_list(:)) > 0) then + keeps(:) = pack(keeps(:), .not. lspill_list(:)) + else + deallocate(keeps) + end if + end if + + return + end subroutine util_spill_arr_char_string + + module subroutine 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 + 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 + + if (.not.allocated(keeps) .or. count(lspill_list(:)) == 0) return + if (.not.allocated(discards)) allocate(discards(count(lspill_list(:)))) + + discards(:) = pack(keeps(:), lspill_list(:)) + if (ldestructive) then + if (count(.not.lspill_list(:)) > 0) then + keeps(:) = pack(keeps(:), .not. lspill_list(:)) + else + deallocate(keeps) + end if + end if + + return + end subroutine util_spill_arr_DP + + module subroutine 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 + 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 + ! Internals + integer(I4B) :: i + + if (.not.allocated(keeps) .or. count(lspill_list(:)) == 0) return + if (.not.allocated(discards)) allocate(discards(NDIM, count(lspill_list(:)))) + + do i = 1, NDIM + discards(i,:) = pack(keeps(i,:), lspill_list(:)) + end do + if (ldestructive) then + if (count(.not.lspill_list(:)) > 0) then + do i = 1, NDIM + keeps(i,:) = pack(keeps(i,:), .not. lspill_list(:)) + end do + end if + end if + + return + end subroutine util_spill_arr_DPvec + + module subroutine 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 + 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 + + if (.not.allocated(keeps) .or. count(lspill_list(:)) == 0) return + if (.not.allocated(discards)) allocate(discards(count(lspill_list(:)))) + + discards(:) = pack(keeps(:), lspill_list(:)) + if (ldestructive) then + if (count(.not.lspill_list(:)) > 0) then + keeps(:) = pack(keeps(:), .not. lspill_list(:)) + else + deallocate(keeps) + end if + end if + + return + end subroutine util_spill_arr_I4B + + module subroutine 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 + 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 + + if (.not.allocated(keeps) .or. count(lspill_list(:)) == 0) return + if (.not.allocated(discards)) allocate(discards(count(lspill_list(:)))) + + discards(:) = pack(keeps(:), lspill_list(:)) + if (ldestructive) then + if (count(.not.lspill_list(:)) > 0) then + keeps(:) = pack(keeps(:), .not. lspill_list(:)) + else + deallocate(keeps) + end if + end if + + return + end subroutine util_spill_arr_logical + + + module subroutine util_spill_body(self, discards, lspill_list, ldestructive) + !! author: David A. Minton + !! + !! Move spilled (discarded) Swiftest generic particle structure from active list to discard list + !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 + implicit none + ! Arguments + class(swiftest_body), intent(inout) :: self !! Swiftest generic 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 + ! Internals + integer(I4B) :: i + + ! For each component, pack the discarded bodies into the discard object and do the inverse with the keeps + !> Spill all the common components + associate(keeps => self) + call util_spill(keeps%id, discards%id, lspill_list, ldestructive) + call util_spill(keeps%name, discards%name, lspill_list, ldestructive) + call util_spill(keeps%status, discards%status, lspill_list, ldestructive) + call util_spill(keeps%lmask, discards%lmask, lspill_list, ldestructive) + call util_spill(keeps%mu, discards%mu, lspill_list, ldestructive) + call util_spill(keeps%xh, discards%xh, lspill_list, ldestructive) + call util_spill(keeps%vh, discards%vh, lspill_list, ldestructive) + call util_spill(keeps%xb, discards%xb, lspill_list, ldestructive) + call util_spill(keeps%vb, discards%vb, lspill_list, ldestructive) + call util_spill(keeps%ah, discards%ah, lspill_list, ldestructive) + call util_spill(keeps%aobl, discards%aobl, lspill_list, ldestructive) + call util_spill(keeps%agr, discards%agr, lspill_list, ldestructive) + call util_spill(keeps%atide, discards%atide, lspill_list, ldestructive) + call util_spill(keeps%a, discards%a, lspill_list, ldestructive) + call util_spill(keeps%e, discards%e, lspill_list, ldestructive) + call util_spill(keeps%inc, discards%inc, lspill_list, ldestructive) + call util_spill(keeps%capom, discards%capom, lspill_list, ldestructive) + call util_spill(keeps%omega, discards%omega, lspill_list, ldestructive) + call util_spill(keeps%capm, discards%capm, lspill_list, ldestructive) + + ! This is the base class, so will be the last to be called in the cascade. + ! Therefore we need to set the nbody values for both the keeps and discareds + discards%nbody = count(lspill_list(:)) + keeps%nbody = count(.not.lspill_list(:)) + if (allocated(keeps%ldiscard)) deallocate(keeps%ldiscard) + if (allocated(discards%ldiscard)) deallocate(discards%ldiscard) + allocate(keeps%ldiscard(keeps%nbody)) + allocate(discards%ldiscard(discards%nbody)) + keeps%ldiscard = .false. + discards%ldiscard = .true. + end associate + + return + end subroutine util_spill_body + + + module subroutine util_spill_pl(self, discards, lspill_list, ldestructive) + !! author: David A. Minton + !! + !! Move spilled (discarded) Swiftest massive body structure from active list to discard list + !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 + implicit none + ! Arguments + 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 body by removing the discard list + ! Internals + integer(I4B) :: i + + associate(keeps => self) + + select type (discards) ! The standard requires us to select the type of both arguments in order to access all the components + class is (swiftest_pl) + !> Spill components specific to the massive body class + call util_spill(keeps%mass, discards%mass, lspill_list, ldestructive) + call util_spill(keeps%Gmass, discards%Gmass, lspill_list, ldestructive) + call util_spill(keeps%rhill, discards%rhill, lspill_list, ldestructive) + call util_spill(keeps%radius, discards%radius, lspill_list, ldestructive) + call util_spill(keeps%density, discards%density, lspill_list, ldestructive) + call util_spill(keeps%k2, discards%k2, lspill_list, ldestructive) + call util_spill(keeps%Q, discards%Q, lspill_list, ldestructive) + call util_spill(keeps%tlag, discards%tlag, lspill_list, ldestructive) + call util_spill(keeps%xbeg, discards%xbeg, lspill_list, ldestructive) + call util_spill(keeps%vbeg, discards%vbeg, lspill_list, ldestructive) + call util_spill(keeps%Ip, discards%Ip, lspill_list, ldestructive) + call util_spill(keeps%rot, discards%rot, lspill_list, ldestructive) + + call util_spill_body(keeps, discards, lspill_list, ldestructive) + class default + write(*,*) 'Error! spill method called for incompatible return type on swiftest_pl' + end select + end associate + + return + end subroutine util_spill_pl + + + module subroutine util_spill_tp(self, discards, lspill_list, ldestructive) + !! author: David A. Minton + !! + !! Move spilled (discarded) Swiftest test particle structure from active list to discard list + !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 + implicit none + ! Arguments + 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 discardse + logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter body by removing the discard list + + associate(keeps => self, ntp => self%nbody) + select type(discards) + class is (swiftest_tp) + !> Spill components specific to the test particle class + call util_spill(keeps%isperi, discards%isperi, lspill_list, ldestructive) + call util_spill(keeps%peri, discards%peri, lspill_list, ldestructive) + call util_spill(keeps%atp, discards%atp, lspill_list, ldestructive) + + call util_spill_body(keeps, discards, lspill_list, ldestructive) + class default + write(*,*) 'Error! spill method called for incompatible return type on swiftest_tp' + end select + end associate + + return + end subroutine util_spill_tp + +end submodule s_util_spill \ No newline at end of file diff --git a/src/whm/whm_util.f90 b/src/whm/whm_util.f90 index ab5461f2d..dbcd9c916 100644 --- a/src/whm/whm_util.f90 +++ b/src/whm/whm_util.f90 @@ -2,7 +2,7 @@ use swiftest contains - module subroutine whm_util_copy_spill_pl(self, discards, lspill_list) + module subroutine whm_util_spill_pl(self, discards, lspill_list, ldestructive) !! author: David A. Minton !! !! Move spilled (discarded) WHM test particle structure from active list to discard list @@ -13,39 +13,29 @@ module subroutine whm_util_copy_spill_pl(self, discards, lspill_list) class(whm_pl), intent(inout) :: self !! WHM 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 ! Internals integer(I4B) :: i associate(keeps => self) select type(discards) class is (whm_pl) - discards%eta(:) = pack(keeps%eta(:), lspill_list(:)) - discards%muj(:) = pack(keeps%muj(:), lspill_list(:)) - discards%ir3j(:) = pack(keeps%ir3j(:), lspill_list(:)) - do i = 1, NDIM - discards%xj(i, :) = pack(keeps%xj(i, :), lspill_list(:)) - discards%vj(i, :) = pack(keeps%vj(i, :), lspill_list(:)) - end do - - if (count(.not.lspill_list(:)) > 0) then - keeps%eta(:) = pack(keeps%eta(:), .not. lspill_list(:)) - keeps%muj(:) = pack(keeps%muj(:), .not. lspill_list(:)) - keeps%ir3j(:) = pack(keeps%ir3j(:), .not. lspill_list(:)) - do i = 1, NDIM - keeps%xj(i, :) = pack(keeps%xj(i, :), .not. lspill_list(:)) - keeps%vj(i, :) = pack(keeps%vj(i, :), .not. lspill_list(:)) - end do - end if - call util_copy_spill_pl(keeps, discards, lspill_list) + call util_spill(keeps%eta, discards%eta, lspill_list, ldestructive) + call util_spill(keeps%muj, discards%muj, lspill_list, ldestructive) + call util_spill(keeps%ir3j, discards%ir3j, lspill_list, ldestructive) + call util_spill(keeps%xj, discards%xj, lspill_list, ldestructive) + call util_spill(keeps%vj, discards%vj, lspill_list, ldestructive) + + call util_spill_pl(keeps, discards, lspill_list, ldestructive) class default write(*,*) 'Error! spill method called for incompatible return type on whm_pl' end select end associate return - end subroutine whm_util_copy_spill_pl + end subroutine whm_util_spill_pl - module subroutine whm_util_copy_fill_pl(self, inserts, lfill_list) + module subroutine whm_util_fill_pl(self, inserts, lfill_list) !! author: David A. Minton !! !! Insert new WHM test particle structure into an old one. @@ -69,14 +59,14 @@ module subroutine whm_util_copy_fill_pl(self, inserts, lfill_list) call util_fill(keeps%xj, inserts%xj, lfill_list) call util_fill(keeps%vj, inserts%vj, lfill_list) - call util_copy_fill_pl(keeps, inserts, lfill_list) + call util_fill_pl(keeps, inserts, lfill_list) class default write(*,*) 'Error! fill method called for incompatible return type on whm_pl' end select end associate return - end subroutine whm_util_copy_fill_pl + end subroutine whm_util_fill_pl module subroutine whm_util_set_ir3j(self) From be0055534896a2efca42e575eed103e37554e28d Mon Sep 17 00:00:00 2001 From: David Minton Date: Mon, 2 Aug 2021 06:21:39 -0400 Subject: [PATCH 08/42] Added info and kinship types to the fill and spill interfaces --- src/modules/symba_classes.f90 | 97 +++++++++++----- src/symba/symba_util.f90 | 208 ++++++++++++++++++++++++---------- 2 files changed, 214 insertions(+), 91 deletions(-) diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index f0cf9e00d..eb6a74482 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -418,6 +418,36 @@ module subroutine symba_step_reset_system(self) class(symba_nbody_system), intent(inout) :: self !! SyMBA nbody system object end subroutine symba_step_reset_system + module subroutine symba_util_copy_pltpenc(self, source) + implicit none + class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list + class(symba_pltpenc), intent(in) :: source !! Source object to copy into + end subroutine symba_util_copy_pltpenc + + module subroutine symba_util_copy_plplenc(self, source) + implicit none + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_pltpenc), intent(in) :: source !! Source object to copy into + end subroutine symba_util_copy_plplenc + end interface + + interface util_fill + module subroutine symba_util_fill_arr_char_info(keeps, inserts, lfill_list) + implicit none + type(symba_particle_info), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + type(symba_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 symba_util_fill_arr_char_info + + module subroutine symba_util_fill_arr_char_kin(keeps, inserts, lfill_list) + implicit none + type(symba_kinship), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + type(symba_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 symba_util_fill_arr_char_kin + end interface + + interface module subroutine symba_util_fill_pl(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none @@ -434,42 +464,12 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps end subroutine symba_util_fill_tp - module subroutine symba_util_copy_pltpenc(self, source) - implicit none - class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - class(symba_pltpenc), intent(in) :: source !! Source object to copy into - end subroutine symba_util_copy_pltpenc - - module subroutine symba_util_copy_plplenc(self, source) - implicit none - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list - class(symba_pltpenc), intent(in) :: source !! Source object to copy into - end subroutine symba_util_copy_plplenc - module subroutine symba_util_resize_pltpenc(self, nrequested) implicit none class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list integer(I4B), intent(in) :: nrequested !! New size of list needed end subroutine symba_util_resize_pltpenc - module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) - use swiftest_classes, only : swiftest_body - implicit none - 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 the keeps array or not - end subroutine symba_util_spill_pl - - module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) - use swiftest_classes, only : swiftest_body - implicit none - 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 the keeps array or not - end subroutine symba_util_spill_tp - module subroutine symba_util_sort_pl(self, sortby, ascending) implicit none class(symba_pl), intent(inout) :: self !! SyMBA massive body object @@ -495,7 +495,44 @@ module subroutine symba_util_sort_rearrange_tp(self, ind) class(symba_tp), 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) end subroutine symba_util_sort_rearrange_tp + end interface + + interface util_spill + module subroutine symba_util_spill_arr_info(keeps, discards, lspill_list, ldestructive) + implicit none + type(symba_particle_info), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + type(symba_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 symba_util_spill_arr_info + + module subroutine symba_util_spill_arr_kin(keeps, discards, lspill_list, ldestructive) + implicit none + type(symba_kinship), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + type(symba_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 symba_util_spill_arr_kin + end interface + interface + module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) + use swiftest_classes, only : swiftest_body + implicit none + 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 the keeps array or not + end subroutine symba_util_spill_pl + + module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) + use swiftest_classes, only : swiftest_body + implicit none + 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 the keeps array or not + end subroutine symba_util_spill_tp end interface end module symba_classes \ No newline at end of file diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 8c9a0a1d7..d1d7fc59e 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -2,6 +2,92 @@ use swiftest contains + module subroutine symba_util_copy_pltpenc(self, source) + !! author: David A. Minton + !! + !! Copies elements from the source encounter list into self. + implicit none + ! Arguments + class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list + class(symba_pltpenc), intent(in) :: source !! Source object to copy into + + associate(n => source%nenc) + self%nenc = n + self%lvdotr(1:n) = source%lvdotr(1:n) + self%status(1:n) = source%status(1:n) + self%level(1:n) = source%level(1:n) + self%index1(1:n) = source%index1(1:n) + self%index2(1:n) = source%index2(1:n) + end associate + + return + end subroutine symba_util_copy_pltpenc + + + module subroutine symba_util_copy_plplenc(self, source) + !! author: David A. Minton + !! + !! Copies elements from the source encounter list into self. + implicit none + ! Arguments + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_pltpenc), intent(in) :: source !! Source object to copy into + + call symba_util_copy_pltpenc(self, source) + associate(n => source%nenc) + select type(source) + class is (symba_plplenc) + self%xh1(:,1:n) = source%xh1(:,1:n) + self%xh2(:,1:n) = source%xh2(:,1:n) + self%vb1(:,1:n) = source%vb1(:,1:n) + self%vb2(:,1:n) = source%vb2(:,1:n) + end select + end associate + + return + end subroutine symba_util_copy_plplenc + + + module subroutine symba_util_fill_arr_char_info(keeps, inserts, lfill_list) + !! author: David A. Minton + !! + !! Performs a fill operation on a single array of particle origin information types + !! This is the inverse of a spill operation + implicit none + ! Arguments + type(symba_particle_info), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + type(symba_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 + + if (.not.allocated(keeps) .or. .not.allocated(inserts)) return + + keeps(:) = unpack(keeps(:), .not.lfill_list(:), keeps(:)) + keeps(:) = unpack(inserts(:), lfill_list(:), keeps(:)) + + return + end subroutine symba_util_fill_arr_char_info + + + module subroutine symba_util_fill_arr_char_kin(keeps, inserts, lfill_list) + !! author: David A. Minton + !! + !! Performs a fill operation on a single array of particle kinship types + !! This is the inverse of a spill operation + implicit none + ! Arguments + type(symba_kinship), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + type(symba_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 + + if (.not.allocated(keeps) .or. .not.allocated(inserts)) return + + keeps(:) = unpack(keeps(:), .not.lfill_list(:), keeps(:)) + keeps(:) = unpack(inserts(:), lfill_list(:), keeps(:)) + + return + end subroutine symba_util_fill_arr_char_kin + + module subroutine symba_util_fill_pl(self, inserts, lfill_list) !! author: David A. Minton !! @@ -27,12 +113,8 @@ module subroutine symba_util_fill_pl(self, inserts, lfill_list) call util_fill(keeps%isperi, inserts%isperi, lfill_list) call util_fill(keeps%peri, inserts%peri, lfill_list) call util_fill(keeps%atp, inserts%atp, lfill_list) - - keeps%kin(:) = unpack(keeps%kin(:), .not.lfill_list(:), keeps%kin(:)) - keeps%kin(:) = unpack(inserts%kin(:), lfill_list(:), keeps%kin(:)) - - keeps%info(:) = unpack(keeps%info(:), .not.lfill_list(:), keeps%info(:)) - keeps%info(:) = unpack(inserts%info(:), lfill_list(:), keeps%info(:)) + call util_fill(keeps%kin, inserts%kin, lfill_list) + call util_fill(keeps%info, inserts%info, lfill_list) call util_fill_pl(keeps, inserts, lfill_list) class default @@ -43,6 +125,7 @@ module subroutine symba_util_fill_pl(self, inserts, lfill_list) return end subroutine symba_util_fill_pl + module subroutine symba_util_fill_tp(self, inserts, lfill_list) !! author: David A. Minton !! @@ -71,51 +154,6 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) return end subroutine symba_util_fill_tp - module subroutine symba_util_copy_pltpenc(self, source) - !! author: David A. Minton - !! - !! Copies elements from the source encounter list into self. - implicit none - ! Arguments - class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - class(symba_pltpenc), intent(in) :: source !! Source object to copy into - - associate(n => source%nenc) - self%nenc = n - self%lvdotr(1:n) = source%lvdotr(1:n) - self%status(1:n) = source%status(1:n) - self%level(1:n) = source%level(1:n) - self%index1(1:n) = source%index1(1:n) - self%index2(1:n) = source%index2(1:n) - end associate - - return - end subroutine symba_util_copy_pltpenc - - - module subroutine symba_util_copy_plplenc(self, source) - !! author: David A. Minton - !! - !! Copies elements from the source encounter list into self. - implicit none - ! Arguments - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list - class(symba_pltpenc), intent(in) :: source !! Source object to copy into - - call symba_util_copy_pltpenc(self, source) - associate(n => source%nenc) - select type(source) - class is (symba_plplenc) - self%xh1(:,1:n) = source%xh1(:,1:n) - self%xh2(:,1:n) = source%xh2(:,1:n) - self%vb1(:,1:n) = source%vb1(:,1:n) - self%vb2(:,1:n) = source%vb2(:,1:n) - end select - end associate - - return - end subroutine symba_util_copy_plplenc - module subroutine symba_util_resize_pltpenc(self, nrequested) !! author: David A. Minton @@ -310,6 +348,62 @@ module subroutine symba_util_sort_rearrange_tp(self, ind) end subroutine symba_util_sort_rearrange_tp + module subroutine symba_util_spill_arr_info(keeps, discards, lspill_list, ldestructive) + !! author: David A. Minton + !! + !! Performs a spill operation on a single array of particle origin information types + !! This is the inverse of a spill operation + implicit none + ! Arguments + type(symba_particle_info), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + type(symba_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 + + if (.not.allocated(keeps) .or. count(lspill_list(:)) == 0) return + if (.not.allocated(discards)) allocate(discards(count(lspill_list(:)))) + + discards(:) = pack(keeps(:), lspill_list(:)) + if (ldestructive) then + if (count(.not.lspill_list(:)) > 0) then + keeps(:) = pack(keeps(:), .not. lspill_list(:)) + else + deallocate(keeps) + end if + end if + + return + end subroutine symba_util_spill_arr_info + + + module subroutine symba_util_spill_arr_kin(keeps, discards, lspill_list, ldestructive) + !! author: David A. Minton + !! + !! Performs a spill operation on a single array of particle kinships + !! This is the inverse of a spill operation + implicit none + ! Arguments + type(symba_kinship), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep + type(symba_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 + + if (.not.allocated(keeps) .or. count(lspill_list(:)) == 0) return + if (.not.allocated(discards)) allocate(discards(count(lspill_list(:)))) + + discards(:) = pack(keeps(:), lspill_list(:)) + if (ldestructive) then + if (count(.not.lspill_list(:)) > 0) then + keeps(:) = pack(keeps(:), .not. lspill_list(:)) + else + deallocate(keeps) + end if + end if + + return + end subroutine symba_util_spill_arr_kin + + module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) !! author: David A. Minton !! @@ -329,7 +423,6 @@ module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) associate(keeps => self) select type(discards) class is (symba_pl) - call util_spill(keeps%lcollision, discards%lcollision, lspill_list, ldestructive) call util_spill(keeps%lencounter, discards%lencounter, lspill_list, ldestructive) call util_spill(keeps%lmtiny, discards%lmtiny, lspill_list, ldestructive) @@ -340,15 +433,8 @@ module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) call util_spill(keeps%isperi, discards%isperi, lspill_list, ldestructive) call util_spill(keeps%peri, discards%peri, lspill_list, ldestructive) call util_spill(keeps%atp, discards%atp, lspill_list, ldestructive) - discards%info(:) = pack(keeps%info(:), lspill_list(:)) - discards%kin(:) = pack(keeps%kin(:), lspill_list(:)) - - if (ldestructive) then - if (count(.not.lspill_list(:)) > 0) then - keeps%info(:) = pack(keeps%info(:), .not. lspill_list(:)) - keeps%kin(:) = pack(keeps%kin(:), .not. lspill_list(:)) - end if - end if + call util_spill(keeps%info, discards%info, lspill_list, ldestructive) + call util_spill(keeps%kin, discards%kin, lspill_list, ldestructive) call util_spill_pl(keeps, discards, lspill_list, ldestructive) class default From 27af16a6be03e66135dc2a75f27544a56b53f270 Mon Sep 17 00:00:00 2001 From: David Minton Date: Mon, 2 Aug 2021 06:34:43 -0400 Subject: [PATCH 09/42] Corrected problem with the rmvs_pl rearrange code and added allocation checks to each component in the rearrange implementation --- src/rmvs/rmvs_util.f90 | 18 ++++++------- src/symba/symba_util.f90 | 40 +++++++++++++++-------------- src/util/util_sort.f90 | 55 ++++++++++++++++++++-------------------- src/whm/whm_util.f90 | 10 ++++---- 4 files changed, 61 insertions(+), 62 deletions(-) diff --git a/src/rmvs/rmvs_util.f90 b/src/rmvs/rmvs_util.f90 index e9804bff6..2f7e5f374 100644 --- a/src/rmvs/rmvs_util.f90 +++ b/src/rmvs/rmvs_util.f90 @@ -49,7 +49,6 @@ module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) associate(keeps => self) select type(inserts) class is (rmvs_tp) - call util_fill(keeps%lperi, inserts%lperi, lfill_list) call util_fill(keeps%plperP, inserts%plperP, lfill_list) call util_fill(keeps%plencP, inserts%plencP, lfill_list) @@ -162,11 +161,9 @@ module subroutine rmvs_util_sort_rearrange_pl(self, ind) associate(pl => self, npl => self%nbody) call util_sort_rearrange_pl(pl,ind) allocate(pl_sorted, source=self) - pl%eta(1:npl) = pl_sorted%eta(ind(1:npl)) - pl%xj(:,1:npl) = pl_sorted%xj(:,ind(1:npl)) - pl%vj(:,1:npl) = pl_sorted%vj(:,ind(1:npl)) - pl%muj(1:npl) = pl_sorted%muj(ind(1:npl)) - pl%ir3j(1:npl) = pl_sorted%ir3j(ind(1:npl)) + if (allocated(pl%nenc)) pl%nenc(1:npl) = pl_sorted%nenc(ind(1:npl)) + if (allocated(pl%tpenc1P)) pl%tpenc1P(1:npl) = pl_sorted%tpenc1P(ind(1:npl)) + if (allocated(pl%plind)) pl%plind(1:npl) = pl_sorted%plind(ind(1:npl)) deallocate(pl_sorted) end associate @@ -191,10 +188,10 @@ module subroutine rmvs_util_sort_rearrange_tp(self, ind) associate(tp => self, ntp => self%nbody) call util_sort_rearrange_tp(tp,ind) allocate(tp_sorted, source=self) - tp%lperi(1:ntp) = tp_sorted%lperi(ind(1:ntp)) - tp%plperP(1:ntp) = tp_sorted%plperP(ind(1:ntp)) - tp%plencP(1:ntp) = tp_sorted%plencP(ind(1:ntp)) - tp%xheliocentric(:,1:ntp) = tp_sorted%xheliocentric(:,ind(1:ntp)) + if (allocated(tp%lperi)) tp%lperi(1:ntp) = tp_sorted%lperi(ind(1:ntp)) + if (allocated(tp%plperP)) tp%plperP(1:ntp) = tp_sorted%plperP(ind(1:ntp)) + if (allocated(tp%plencP)) tp%plencP(1:ntp) = tp_sorted%plencP(ind(1:ntp)) + if (allocated(tp%xheliocentric)) tp%xheliocentric(:,1:ntp) = tp_sorted%xheliocentric(:,ind(1:ntp)) deallocate(tp_sorted) end associate @@ -223,6 +220,7 @@ module subroutine rmvs_util_spill_pl(self, discards, lspill_list, ldestructive) call util_spill(keeps%nenc, discards%nenc, lspill_list, ldestructive) call util_spill(keeps%tpenc1P, discards%tpenc1P, lspill_list, ldestructive) call util_spill(keeps%plind, discards%plind, lspill_list, ldestructive) + call whm_util_spill_pl(keeps, discards, lspill_list, ldestructive) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index d1d7fc59e..70941555d 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -299,23 +299,25 @@ module subroutine symba_util_sort_rearrange_pl(self, ind) associate(pl => self, npl => self%nbody) call util_sort_rearrange_pl(pl,ind) allocate(pl_sorted, source=self) - pl%lcollision(1:npl) = pl_sorted%lcollision(ind(1:npl)) - pl%lencounter(1:npl) = pl_sorted%lencounter(ind(1:npl)) - pl%lmtiny(1:npl) = pl_sorted%lmtiny(ind(1:npl)) - pl%nplenc(1:npl) = pl_sorted%nplenc(ind(1:npl)) - pl%ntpenc(1:npl) = pl_sorted%ntpenc(ind(1:npl)) - pl%levelg(1:npl) = pl_sorted%levelg(ind(1:npl)) - pl%levelm(1:npl) = pl_sorted%levelm(ind(1:npl)) - pl%isperi(1:npl) = pl_sorted%isperi(ind(1:npl)) - pl%peri(1:npl) = pl_sorted%peri(ind(1:npl)) - pl%atp(1:npl) = pl_sorted%atp(ind(1:npl)) - pl%info(1:npl) = pl_sorted%info(ind(1:npl)) - pl%kin(1:npl) = pl_sorted%kin(ind(1:npl)) - do i = 1, npl - do j = 1, pl%kin(i)%nchild - pl%kin(i)%child(j) = ind(pl%kin(i)%child(j)) + if (allocated(pl%lcollision)) pl%lcollision(1:npl) = pl_sorted%lcollision(ind(1:npl)) + if (allocated(pl%lencounter)) pl%lencounter(1:npl) = pl_sorted%lencounter(ind(1:npl)) + if (allocated(pl%lmtiny)) pl%lmtiny(1:npl) = pl_sorted%lmtiny(ind(1:npl)) + if (allocated(pl%nplenc)) pl%nplenc(1:npl) = pl_sorted%nplenc(ind(1:npl)) + if (allocated(pl%ntpenc)) pl%ntpenc(1:npl) = pl_sorted%ntpenc(ind(1:npl)) + if (allocated(pl%levelg)) pl%levelg(1:npl) = pl_sorted%levelg(ind(1:npl)) + if (allocated(pl%levelm)) pl%levelm(1:npl) = pl_sorted%levelm(ind(1:npl)) + if (allocated(pl%isperi)) pl%isperi(1:npl) = pl_sorted%isperi(ind(1:npl)) + if (allocated(pl%peri)) pl%peri(1:npl) = pl_sorted%peri(ind(1:npl)) + if (allocated(pl%atp)) pl%atp(1:npl) = pl_sorted%atp(ind(1:npl)) + if (allocated(pl%info)) pl%info(1:npl) = pl_sorted%info(ind(1:npl)) + if (allocated(pl%kin)) then + pl%kin(1:npl) = pl_sorted%kin(ind(1:npl)) + do i = 1, npl + do j = 1, pl%kin(i)%nchild + pl%kin(i)%child(j) = ind(pl%kin(i)%child(j)) + end do end do - end do + end if deallocate(pl_sorted) end associate @@ -338,9 +340,9 @@ module subroutine symba_util_sort_rearrange_tp(self, ind) associate(tp => self, ntp => self%nbody) call util_sort_rearrange_tp(tp,ind) allocate(tp_sorted, source=self) - tp%nplenc(1:ntp) = tp_sorted%nplenc(ind(1:ntp)) - tp%levelg(1:ntp) = tp_sorted%levelg(ind(1:ntp)) - tp%levelm(1:ntp) = tp_sorted%levelm(ind(1:ntp)) + if (allocated(tp%nplenc)) tp%nplenc(1:ntp) = tp_sorted%nplenc(ind(1:ntp)) + if (allocated(tp%levelg)) tp%levelg(1:ntp) = tp_sorted%levelg(ind(1:ntp)) + if (allocated(tp%levelm)) tp%levelm(1:ntp) = tp_sorted%levelm(ind(1:ntp)) deallocate(tp_sorted) end associate diff --git a/src/util/util_sort.f90 b/src/util/util_sort.f90 index 59f44c003..752e78ab7 100644 --- a/src/util/util_sort.f90 +++ b/src/util/util_sort.f90 @@ -161,28 +161,27 @@ module subroutine util_sort_rearrange_body(self, ind) 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)) - self%ldiscard(1:n) = body_sorted%ldiscard(ind(1:n)) - self%xh(:,1:n) = body_sorted%xh(:,ind(1:n)) - self%vh(:,1:n) = body_sorted%vh(:,ind(1:n)) - self%xb(:,1:n) = body_sorted%xb(:,ind(1:n)) - self%vb(:,1:n) = body_sorted%vb(:,ind(1:n)) - self%ah(:,1:n) = body_sorted%ah(:,ind(1:n)) - self%ir3h(1:n) = body_sorted%ir3h(ind(1:n)) - self%mu(1:n) = body_sorted%mu(ind(1:n)) - self%lmask(1:n) = body_sorted%lmask(ind(1:n)) - - if (allocated(self%a)) self%a(1:n) = body_sorted%a(ind(1:n)) - if (allocated(self%e)) self%e(1:n) = body_sorted%e(ind(1:n)) - if (allocated(self%inc)) self%inc(1:n) = body_sorted%inc(ind(1:n)) - if (allocated(self%capom)) self%capom(1:n) = body_sorted%capom(ind(1:n)) - if (allocated(self%omega)) self%omega(1:n) = body_sorted%omega(ind(1:n)) - if (allocated(self%capm)) self%capm(1:n) = body_sorted%capm(ind(1:n)) - if (allocated(self%aobl)) self%aobl(:,1:n) = body_sorted%aobl(:,ind(1:n)) - if (allocated(self%atide)) self%atide(:,1:n) = body_sorted%atide(:,ind(1:n)) - if (allocated(self%agr)) self%agr(:,1:n) = body_sorted%agr(:,ind(1:n)) + if (allocated(self%id)) self%id(1:n) = body_sorted%id(ind(1:n)) + if (allocated(self%name)) self%name(1:n) = body_sorted%name(ind(1:n)) + if (allocated(self%status)) self%status(1:n) = body_sorted%status(ind(1:n)) + if (allocated(self%ldiscard)) self%ldiscard(1:n) = body_sorted%ldiscard(ind(1:n)) + if (allocated(self%xh)) self%xh(:,1:n) = body_sorted%xh(:,ind(1:n)) + if (allocated(self%vh)) self%vh(:,1:n) = body_sorted%vh(:,ind(1:n)) + if (allocated(self%xb)) self%xb(:,1:n) = body_sorted%xb(:,ind(1:n)) + if (allocated(self%vb)) self%vb(:,1:n) = body_sorted%vb(:,ind(1:n)) + if (allocated(self%ah)) self%ah(:,1:n) = body_sorted%ah(:,ind(1:n)) + if (allocated(self%ir3h)) self%ir3h(1:n) = body_sorted%ir3h(ind(1:n)) + if (allocated(self%mu)) self%mu(1:n) = body_sorted%mu(ind(1:n)) + if (allocated(self%lmask)) self%lmask(1:n) = body_sorted%lmask(ind(1:n)) + if (allocated(self%a)) self%a(1:n) = body_sorted%a(ind(1:n)) + if (allocated(self%e)) self%e(1:n) = body_sorted%e(ind(1:n)) + if (allocated(self%inc)) self%inc(1:n) = body_sorted%inc(ind(1:n)) + if (allocated(self%capom)) self%capom(1:n) = body_sorted%capom(ind(1:n)) + if (allocated(self%omega)) self%omega(1:n) = body_sorted%omega(ind(1:n)) + if (allocated(self%capm)) self%capm(1:n) = body_sorted%capm(ind(1:n)) + if (allocated(self%aobl)) self%aobl(:,1:n) = body_sorted%aobl(:,ind(1:n)) + if (allocated(self%atide)) self%atide(:,1:n) = body_sorted%atide(:,ind(1:n)) + if (allocated(self%agr)) self%agr(:,1:n) = body_sorted%agr(:,ind(1:n)) deallocate(body_sorted) end associate @@ -204,9 +203,9 @@ module subroutine util_sort_rearrange_pl(self, ind) associate(pl => self, npl => self%nbody) call util_sort_rearrange_body(pl,ind) allocate(pl_sorted, source=self) - pl%mass(1:npl) = pl_sorted%mass(ind(1:npl)) - pl%Gmass(1:npl) = pl_sorted%Gmass(ind(1:npl)) - pl%rhill(1:npl) = pl_sorted%rhill(ind(1:npl)) + if (allocated(pl%mass)) pl%mass(1:npl) = pl_sorted%mass(ind(1:npl)) + if (allocated(pl%Gmass)) pl%Gmass(1:npl) = pl_sorted%Gmass(ind(1:npl)) + if (allocated(pl%rhill)) pl%rhill(1:npl) = pl_sorted%rhill(ind(1:npl)) if (allocated(pl%xbeg)) pl%xbeg(:,1:npl) = pl_sorted%xbeg(:,ind(1:npl)) if (allocated(pl%xend)) pl%xend(:,1:npl) = pl_sorted%xend(:,ind(1:npl)) if (allocated(pl%vbeg)) pl%vbeg(:,1:npl) = pl_sorted%vbeg(:,ind(1:npl)) @@ -240,9 +239,9 @@ module subroutine util_sort_rearrange_tp(self, ind) associate(tp => self, ntp => self%nbody) call util_sort_rearrange_body(tp,ind) allocate(tp_sorted, source=self) - tp%isperi(1:ntp) = tp_sorted%isperi(ind(1:ntp)) - tp%peri(1:ntp) = tp_sorted%peri(ind(1:ntp)) - tp%atp(1:ntp) = tp_sorted%atp(ind(1:ntp)) + if (allocated(tp%isperi)) tp%isperi(1:ntp) = tp_sorted%isperi(ind(1:ntp)) + if (allocated(tp%peri)) tp%peri(1:ntp) = tp_sorted%peri(ind(1:ntp)) + if (allocated(tp%atp)) tp%atp(1:ntp) = tp_sorted%atp(ind(1:ntp)) deallocate(tp_sorted) end associate diff --git a/src/whm/whm_util.f90 b/src/whm/whm_util.f90 index dbcd9c916..deb5dde5a 100644 --- a/src/whm/whm_util.f90 +++ b/src/whm/whm_util.f90 @@ -155,11 +155,11 @@ module subroutine whm_util_sort_rearrange_pl(self, ind) associate(pl => self, npl => self%nbody) call util_sort_rearrange_pl(pl,ind) allocate(pl_sorted, source=self) - pl%eta(1:npl) = pl_sorted%eta(ind(1:npl)) - pl%xj(:,1:npl) = pl_sorted%xj(:,ind(1:npl)) - pl%vj(:,1:npl) = pl_sorted%vj(:,ind(1:npl)) - pl%muj(1:npl) = pl_sorted%muj(ind(1:npl)) - pl%ir3j(1:npl) = pl_sorted%ir3j(ind(1:npl)) + if (allocated(pl%eta)) pl%eta(1:npl) = pl_sorted%eta(ind(1:npl)) + if (allocated(pl%xj)) pl%xj(:,1:npl) = pl_sorted%xj(:,ind(1:npl)) + if (allocated(pl%vj)) pl%vj(:,1:npl) = pl_sorted%vj(:,ind(1:npl)) + if (allocated(pl%muj)) pl%muj(1:npl) = pl_sorted%muj(ind(1:npl)) + if (allocated(pl%ir3j)) pl%ir3j(1:npl) = pl_sorted%ir3j(ind(1:npl)) deallocate(pl_sorted) end associate From ff9578934a8fbb3d6b7d3245c090a1a331b10cff Mon Sep 17 00:00:00 2001 From: David Minton Date: Mon, 2 Aug 2021 08:07:25 -0400 Subject: [PATCH 10/42] Added generic resize methods to all body types --- src/modules/rmvs_classes.f90 | 16 +- src/modules/swiftest_classes.f90 | 59 ++++++- src/modules/symba_classes.f90 | 58 +++++-- src/modules/whm_classes.f90 | 90 ++++++----- src/rmvs/rmvs_util.f90 | 46 ++++++ src/symba/symba_util.f90 | 131 +++++++++++++++- src/util/util_append.f90 | 2 +- src/util/util_copy.f90 | 2 +- src/util/util_resize.f90 | 262 ++++++++++++++++++++++++++++--- src/whm/whm_util.f90 | 21 +++ 10 files changed, 592 insertions(+), 95 deletions(-) diff --git a/src/modules/rmvs_classes.f90 b/src/modules/rmvs_classes.f90 index 4c3bac64f..49794b1ef 100644 --- a/src/modules/rmvs_classes.f90 +++ b/src/modules/rmvs_classes.f90 @@ -72,6 +72,7 @@ module rmvs_classes !! if the test particle is undergoing a close encounter or not procedure :: setup => rmvs_setup_tp !! Constructor method - Allocates space for number of particles procedure :: fill => rmvs_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: resize => rmvs_util_resize_tp !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => rmvs_util_sort_tp !! Sorts body arrays by a sortable componen procedure :: rearrange => rmvs_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods procedure :: spill => rmvs_util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) @@ -92,9 +93,10 @@ module rmvs_classes logical :: lplanetocentric = .false. !! Flag that indicates that the object is a planetocentric set of masive bodies used for close encounter calculations contains procedure :: setup => rmvs_setup_pl !! Constructor method - Allocates space for number of particles + procedure :: fill => rmvs_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: resize => rmvs_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => rmvs_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => rmvs_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: fill => rmvs_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: spill => rmvs_util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type rmvs_pl @@ -170,6 +172,18 @@ module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps end subroutine rmvs_util_fill_tp + module subroutine rmvs_util_resize_pl(self, nnew) + implicit none + class(rmvs_pl), intent(inout) :: self !! RMVS massive body object + integer(I4B), intent(in) :: nnew !! New size neded + end subroutine rmvs_util_resize_pl + + module subroutine rmvs_util_resize_tp(self, nnew) + implicit none + class(rmvs_tp), intent(inout) :: self !! RMVS test particle object + integer(I4B), intent(in) :: nnew !! New size neded + end subroutine rmvs_util_resize_tp + module subroutine rmvs_util_sort_pl(self, sortby, ascending) implicit none class(rmvs_pl), intent(inout) :: self !! RMVS massive body object diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index be342756e..00802f3fa 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -127,6 +127,8 @@ module swiftest_classes integer(I4B), dimension(:), allocatable :: id !! External identifier (unique) integer(I4B), dimension(:), allocatable :: status !! An integrator-specific status indicator logical, dimension(:), allocatable :: ldiscard !! Body should be discarded + logical, dimension(:), allocatable :: lmask !! Logical mask used to select a subset of bodies when performing certain operations (drift, kick, accel, etc.) + real(DP), dimension(:), allocatable :: mu !! G * (Mcb + [m]) real(DP), dimension(:,:), allocatable :: xh !! Heliocentric position real(DP), dimension(:,:), allocatable :: vh !! Heliocentric velocity real(DP), dimension(:,:), allocatable :: xb !! Barycentric position @@ -142,8 +144,6 @@ module swiftest_classes real(DP), dimension(:), allocatable :: capom !! Longitude of ascending node real(DP), dimension(:), allocatable :: omega !! Argument of pericenter real(DP), dimension(:), allocatable :: capm !! Mean anomaly - real(DP), dimension(:), allocatable :: mu !! G * (Mcb + [m]) - logical, dimension(:), allocatable :: lmask !! Logical mask used to select a subset of bodies when performing certain operations (drift, kick, accel, etc.) !! 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 @@ -209,6 +209,7 @@ module swiftest_classes procedure :: h2b => util_coord_h2b_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) procedure :: b2h => util_coord_b2h_pl !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) procedure :: fill => util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: resize => util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: set_beg_end => util_set_beg_end_pl !! Sets the beginning and ending positions and velocities of planets. procedure :: set_mu => util_set_mu_pl !! Method used to construct the vectorized form of the central body mass procedure :: set_rhill => util_set_rhill !! Calculates the Hill's radii for each body @@ -239,6 +240,7 @@ module swiftest_classes procedure :: b2h => util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) procedure :: fill => util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: get_peri => util_peri_tp !! Determine system pericenter passages for test particles + procedure :: resize => 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 => util_set_mu_tp !! Method used to construct the vectorized form of the central body mass procedure :: sort => util_sort_tp !! Sorts body arrays by a sortable component procedure :: rearrange => util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods @@ -847,14 +849,59 @@ module subroutine util_peri_tp(self, system, param) class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters end subroutine util_peri_tp + end interface + + interface util_resize + module subroutine util_resize_arr_char_string(arr, nnew) + implicit none + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + end subroutine util_resize_arr_char_string + + module subroutine util_resize_arr_DP(arr, nnew) + implicit none + real(DP), dimension(:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + end subroutine util_resize_arr_DP + + module subroutine util_resize_arr_DPvec(arr, nnew) + implicit none + real(DP), dimension(:,:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + end subroutine util_resize_arr_DPvec + + module subroutine util_resize_arr_I4B(arr, nnew) + implicit none + integer(I4B), dimension(:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + end subroutine util_resize_arr_I4B + + module subroutine util_resize_arr_logical(arr, nnew) + implicit none + logical, dimension(:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + end subroutine util_resize_arr_logical + end interface - module subroutine util_resize_body(self, nrequested, param) + interface + module subroutine util_resize_body(self, nnew) implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - integer(I4B), intent(in) :: nrequested !! New size neded - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_body), intent(inout) :: self !! Swiftest body object + integer(I4B), intent(in) :: nnew !! New size neded end subroutine util_resize_body + module subroutine 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 + end subroutine util_resize_pl + + module subroutine 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 + end subroutine util_resize_tp + module subroutine util_set_beg_end_pl(self, xbeg, xend, vbeg) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index eb6a74482..712b98f65 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -92,10 +92,11 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_pl !! Checks if massive bodies are going through close encounters with each other procedure :: accel => symba_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies procedure :: setup => symba_setup_pl !! Constructor method - Allocates space for number of particle - procedure :: fill => symba_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => symba_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: resize => symba_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => symba_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => symba_util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => symba_util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type symba_pl !******************************************************************************************************************************** @@ -111,10 +112,11 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_tp !! Checks if any test particles are undergoing a close encounter with a massive body procedure :: accel => symba_kick_getacch_tp !! Compute heliocentric accelerations of test particles procedure :: setup => symba_setup_tp !! Constructor method - Allocates space for number of particle - procedure :: fill => symba_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: fill => symba_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: resize => symba_util_resize_tp !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => symba_util_sort_tp !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => symba_util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: spill => symba_util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type symba_tp !******************************************************************************************************************************** @@ -163,12 +165,12 @@ module symba_classes class(symba_pl), allocatable :: pl_discards !! Discarded test particle data structure integer(I4B) :: irec !! System recursion level contains - procedure :: initialize => symba_setup_initialize_system !! Performs SyMBA-specific initilization steps - procedure :: step => symba_step_system !! Advance the SyMBA nbody system forward in time by one step - procedure :: interp => symba_step_interp_system !! Perform an interpolation step on the SymBA nbody system - procedure :: set_recur_levels => symba_step_set_recur_levels_system !! Sets recursion levels of bodies and encounter lists to the current system level - procedure :: recursive_step => symba_step_recur_system !! Step interacting planets and active test particles ahead in democratic heliocentric coordinates at the current recursion level, if applicable, and descend to the next deeper level if necessary - procedure :: reset => symba_step_reset_system !! Resets pl, tp,and encounter structures at the start of a new step + procedure :: initialize => symba_setup_initialize_system !! Performs SyMBA-specific initilization steps + procedure :: step => symba_step_system !! Advance the SyMBA nbody system forward in time by one step + procedure :: interp => symba_step_interp_system !! Perform an interpolation step on the SymBA nbody system + procedure :: set_recur_levels => symba_step_set_recur_levels_system !! Sets recursion levels of bodies and encounter lists to the current system level + procedure :: recursive_step => symba_step_recur_system !! Step interacting planets and active test particles ahead in democratic heliocentric coordinates at the current recursion level, if applicable, and descend to the next deeper level if necessary + procedure :: reset => symba_step_reset_system !! Resets pl, tp,and encounter structures at the start of a new step end type symba_nbody_system interface @@ -439,12 +441,12 @@ module subroutine symba_util_fill_arr_char_info(keeps, inserts, lfill_list) logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps end subroutine symba_util_fill_arr_char_info - module subroutine symba_util_fill_arr_char_kin(keeps, inserts, lfill_list) + module subroutine symba_util_fill_arr_kin(keeps, inserts, lfill_list) implicit none type(symba_kinship), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep type(symba_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 symba_util_fill_arr_char_kin + end subroutine symba_util_fill_arr_kin end interface interface @@ -463,13 +465,41 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) class(swiftest_body), intent(in) :: inserts !! Inserted object logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps end subroutine symba_util_fill_tp + end interface + + interface util_resize + module subroutine symba_util_resize_arr_info(arr, nnew) + implicit none + type(symba_particle_info), dimension(:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + end subroutine symba_util_resize_arr_info - module subroutine symba_util_resize_pltpenc(self, nrequested) + module subroutine symba_util_resize_arr_kin(arr, nnew) + implicit none + type(symba_kinship), dimension(:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + end subroutine symba_util_resize_arr_kin + end interface + + interface + module subroutine symba_util_resize_pl(self, nnew) + implicit none + class(symba_pl), intent(inout) :: self !! SyMBA massive body object + integer(I4B), intent(in) :: nnew !! New size neded + end subroutine symba_util_resize_pl + + module subroutine symba_util_resize_pltpenc(self, nnew) implicit none class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - integer(I4B), intent(in) :: nrequested !! New size of list needed + integer(I4B), intent(in) :: nnew !! New size of list needed end subroutine symba_util_resize_pltpenc + module subroutine symba_util_resize_tp(self, nnew) + implicit none + class(symba_tp), intent(inout) :: self !! SyMBA massive body object + integer(I4B), intent(in) :: nnew !! New size neded + end subroutine symba_util_resize_tp + module subroutine symba_util_sort_pl(self, sortby, ascending) implicit none class(symba_pl), intent(inout) :: self !! SyMBA massive body object diff --git a/src/modules/whm_classes.f90 b/src/modules/whm_classes.f90 index 626c0a974..0f67c9432 100644 --- a/src/modules/whm_classes.f90 +++ b/src/modules/whm_classes.f90 @@ -34,18 +34,19 @@ module whm_classes procedure :: j2h => whm_coord_j2h_pl !! Convert position and velcoity vectors from Jacobi to helliocentric coordinates procedure :: vh2vj => whm_coord_vh2vj_pl !! Convert velocity vectors from heliocentric to Jacobi coordinates procedure :: drift => whm_drift_pl !! Loop through massive bodies and call Danby drift routine to jacobi coordinates - procedure :: fill => whm_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) - procedure :: accel => whm_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies - procedure :: kick => whm_kick_vh_pl !! Kick heliocentric velocities of massive bodies procedure :: accel_gr => whm_gr_kick_getacch_pl !! Acceleration term arising from the post-Newtonian correction procedure :: gr_pos_kick => whm_gr_p4_pl !! Position kick due to p**4 term in the post-Newtonian correction - procedure :: setup => whm_setup_pl !! Constructor method - Allocates space for number of particles - procedure :: set_mu => whm_util_set_mu_eta_pl !! Sets the Jacobi mass value for all massive bodies. + procedure :: accel => whm_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies + procedure :: kick => whm_kick_vh_pl !! Kick heliocentric velocities of massive bodies + procedure :: fill => whm_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: resize => whm_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: set_ir3 => whm_util_set_ir3j !! Sets both the heliocentric and jacobi inverse radius terms (1/rj**3 and 1/rh**3) + procedure :: set_mu => whm_util_set_mu_eta_pl !! Sets the Jacobi mass value for all massive bodies. procedure :: sort => whm_util_sort_pl !! Sort a WHM massive body object in-place. procedure :: rearrange => whm_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: step => whm_step_pl !! Steps the body forward one stepsize procedure :: spill => whm_util_spill_pl !!"Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: setup => whm_setup_pl !! Constructor method - Allocates space for number of particles + procedure :: step => whm_step_pl !! Steps the body forward one stepsize end type whm_pl !******************************************************************************************************************************** @@ -57,10 +58,10 @@ module whm_classes !! Note to developers: If you add componenets to this class, be sure to update methods and subroutines that traverse the !! component list, such as whm_util_spill_tp contains - procedure :: accel => whm_kick_getacch_tp !! Compute heliocentric accelerations of test particles - procedure :: kick => whm_kick_vh_tp !! Kick heliocentric velocities of test particles procedure :: accel_gr => whm_gr_kick_getacch_tp !! Acceleration term arising from the post-Newtonian correction procedure :: gr_pos_kick => whm_gr_p4_tp !! Position kick due to p**4 term in the post-Newtonian correction + procedure :: accel => whm_kick_getacch_tp !! Compute heliocentric accelerations of test particles + procedure :: kick => whm_kick_vh_tp !! Kick heliocentric velocities of test particles procedure :: step => whm_step_tp !! Steps the particle forward one stepsize end type whm_tp @@ -106,14 +107,6 @@ module subroutine whm_drift_pl(self, system, param, dt) real(DP), intent(in) :: dt !! Stepsize end subroutine whm_drift_pl - module subroutine whm_util_fill_pl(self, inserts, lfill_list) - use swiftest_classes, only : swiftest_body - implicit none - class(whm_pl), intent(inout) :: self !! WHM massive 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 - end subroutine whm_util_fill_pl - !> Get heliocentric accelration of massive bodies module subroutine whm_kick_getacch_pl(self, system, param, t, lbeg) use swiftest_classes, only : swiftest_cb, swiftest_parameters @@ -197,31 +190,6 @@ module subroutine whm_setup_pl(self, n, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters end subroutine whm_setup_pl - module subroutine whm_util_set_ir3j(self) - implicit none - class(whm_pl), intent(inout) :: self !! WHM massive body object - end subroutine whm_util_set_ir3j - - module subroutine whm_util_set_mu_eta_pl(self, cb) - use swiftest_classes, only : swiftest_cb - implicit none - class(whm_pl), intent(inout) :: self !! WHM massive body object - class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object - end subroutine whm_util_set_mu_eta_pl - - module subroutine whm_util_sort_pl(self, sortby, ascending) - implicit none - class(whm_pl), intent(inout) :: self !! WHM 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 - end subroutine whm_util_sort_pl - - module subroutine whm_util_sort_rearrange_pl(self, ind) - implicit none - class(whm_pl), intent(inout) :: self !! WHM 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 whm_util_sort_rearrange_pl - module subroutine whm_setup_initialize_system(self, param) use swiftest_classes, only : swiftest_parameters implicit none @@ -258,7 +226,6 @@ module subroutine whm_util_spill_pl(self, discards, lspill_list, ldestructive) logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine whm_util_spill_pl - !> Steps the Swiftest nbody system forward in time one stepsize module subroutine whm_step_system(self, param, t, dt) use swiftest_classes, only : swiftest_parameters implicit none @@ -267,6 +234,45 @@ module subroutine whm_step_system(self, param, t, dt) real(DP), intent(in) :: t !! Simulation time real(DP), intent(in) :: dt !! Current stepsize end subroutine whm_step_system + + module subroutine whm_util_fill_pl(self, inserts, lfill_list) + use swiftest_classes, only : swiftest_body + implicit none + class(whm_pl), intent(inout) :: self !! WHM massive 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 + end subroutine whm_util_fill_pl + + module subroutine whm_util_resize_pl(self, nnew) + implicit none + class(whm_pl), intent(inout) :: self !! WHM massive body object + integer(I4B), intent(in) :: nnew !! New size neded + end subroutine whm_util_resize_pl + + module subroutine whm_util_set_ir3j(self) + implicit none + class(whm_pl), intent(inout) :: self !! WHM massive body object + end subroutine whm_util_set_ir3j + + module subroutine whm_util_set_mu_eta_pl(self, cb) + use swiftest_classes, only : swiftest_cb + implicit none + class(whm_pl), intent(inout) :: self !! WHM massive body object + class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object + end subroutine whm_util_set_mu_eta_pl + + module subroutine whm_util_sort_pl(self, sortby, ascending) + implicit none + class(whm_pl), intent(inout) :: self !! WHM 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 + end subroutine whm_util_sort_pl + + module subroutine whm_util_sort_rearrange_pl(self, ind) + implicit none + class(whm_pl), intent(inout) :: self !! WHM 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 whm_util_sort_rearrange_pl end interface end module whm_classes diff --git a/src/rmvs/rmvs_util.f90 b/src/rmvs/rmvs_util.f90 index 2f7e5f374..dcf0de473 100644 --- a/src/rmvs/rmvs_util.f90 +++ b/src/rmvs/rmvs_util.f90 @@ -62,6 +62,52 @@ module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) return end subroutine rmvs_util_fill_tp + + module subroutine rmvs_util_resize_pl(self, nnew) + !! author: David A. Minton + !! + !! Checks the current size of a massive body object against the requested size and resizes it if it is too small. + implicit none + ! Arguments + class(rmvs_pl), intent(inout) :: self !! RMVS massive body object + integer(I4B), intent(in) :: nnew !! New size neded + + call whm_util_resize_pl(self, nnew) + + call util_resize(self%nenc, nnew) + call util_resize(self%tpenc1P, nnew) + call util_resize(self%plind, nnew) + + ! The following are not implemented as RMVS doesn't make use of resize operations on pl type + ! So they are here as a placeholder in case someone wants to extend the RMVS class for some reason + !call util_resize(self%outer, nnew) + !call util_resize(self%inner, nnew) + !call util_resize(self%planetocentric, nnew) + + return + end subroutine rmvs_util_resize_pl + + + module subroutine rmvs_util_resize_tp(self, nnew) + !! author: David A. Minton + !! + !! 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(rmvs_tp), intent(inout) :: self !! RMVS test particle object + integer(I4B), intent(in) :: nnew !! New size neded + + call util_resize_tp(self, nnew) + + call util_resize(self%lperi, nnew) + call util_resize(self%plperP, nnew) + call util_resize(self%plencP, nnew) + call util_resize(self%xheliocentric, nnew) + + return + end subroutine rmvs_util_resize_tp + + module subroutine rmvs_util_sort_pl(self, sortby, ascending) !! author: David A. Minton !! diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 70941555d..f2f72d12d 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -68,7 +68,7 @@ module subroutine symba_util_fill_arr_char_info(keeps, inserts, lfill_list) end subroutine symba_util_fill_arr_char_info - module subroutine symba_util_fill_arr_char_kin(keeps, inserts, lfill_list) + module subroutine symba_util_fill_arr_kin(keeps, inserts, lfill_list) !! author: David A. Minton !! !! Performs a fill operation on a single array of particle kinship types @@ -85,7 +85,7 @@ module subroutine symba_util_fill_arr_char_kin(keeps, inserts, lfill_list) keeps(:) = unpack(inserts(:), lfill_list(:), keeps(:)) return - end subroutine symba_util_fill_arr_char_kin + end subroutine symba_util_fill_arr_kin module subroutine symba_util_fill_pl(self, inserts, lfill_list) @@ -155,7 +155,122 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) end subroutine symba_util_fill_tp - module subroutine symba_util_resize_pltpenc(self, nrequested) + module subroutine symba_util_resize_arr_info(arr, nnew) + !! author: David A. Minton + !! + !! Resizes an array component of type character string. Array will only be resized if has previously been allocated. Passing nnew = 0 will deallocate. + implicit none + ! Arguments + type(symba_particle_info), dimension(:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + ! Internals + type(symba_particle_info), dimension(:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold !! Old size + + if (.not. allocated(arr) .or. nnew < 0) return + + nold = size(arr) + if (nnew == nold) return + + if (nnew == 0) then + deallocate(arr) + return + end if + + allocate(tmp(nnew)) + if (nnew > nold) then + tmp(1:nold) = arr(1:nold) + else + tmp(1:nnew) = arr(1:nnew) + end if + call move_alloc(tmp, arr) + + return + end subroutine symba_util_resize_arr_info + + + module subroutine symba_util_resize_arr_kin(arr, nnew) + !! author: David A. Minton + !! + !! Resizes an array component of type character string. Array will only be resized if has previously been allocated. Passing nnew = 0 will deallocate. + implicit none + ! Arguments + type(symba_kinship), dimension(:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size + ! Internals + type(symba_kinship), dimension(:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold !! Old size + + if (.not. allocated(arr) .or. nnew < 0) return + + nold = size(arr) + if (nnew == nold) return + + if (nnew == 0) then + deallocate(arr) + return + end if + + allocate(tmp(nnew)) + if (nnew > nold) then + tmp(1:nold) = arr(1:nold) + else + tmp(1:nnew) = arr(1:nnew) + end if + call move_alloc(tmp, arr) + + return + end subroutine symba_util_resize_arr_kin + + + module subroutine symba_util_resize_pl(self, nnew) + !! author: David A. Minton + !! + !! Checks the current size of a 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 + + call util_resize_pl(self, nnew) + + call util_resize(self%lcollision, nnew) + call util_resize(self%lencounter, nnew) + call util_resize(self%lmtiny, nnew) + call util_resize(self%nplenc, nnew) + call util_resize(self%ntpenc, nnew) + call util_resize(self%levelg, nnew) + call util_resize(self%levelm, nnew) + call util_resize(self%isperi, nnew) + call util_resize(self%peri, nnew) + call util_resize(self%atp, nnew) + call util_resize(self%kin, nnew) + call util_resize(self%info, nnew) + + return + end subroutine symba_util_resize_pl + + + module subroutine symba_util_resize_tp(self, nnew) + !! author: David A. Minton + !! + !! 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 + + call util_resize_tp(self, nnew) + + call util_resize(self%nplenc, nnew) + call util_resize(self%levelg, nnew) + call util_resize(self%levelm, nnew) + + return + end subroutine symba_util_resize_tp + + + module subroutine symba_util_resize_pltpenc(self, nnew) !! author: David A. Minton !! !! Checks the current size of the encounter list against the required size and extends it by a factor of 2 more than requested if it is too small. @@ -163,7 +278,7 @@ module subroutine symba_util_resize_pltpenc(self, nrequested) implicit none ! Arguments class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - integer(I4B), intent(in) :: nrequested !! New size of list needed + integer(I4B), intent(in) :: nnew !! New size of list needed ! Internals class(symba_pltpenc), allocatable :: enc_temp integer(I4B) :: nold @@ -175,17 +290,17 @@ module subroutine symba_util_resize_pltpenc(self, nrequested) else nold = 0 end if - if (nrequested > nold) then + if (nnew > nold) then if (lmalloc) allocate(enc_temp, source=self) - call self%setup(2 * nrequested) + call self%setup(2 * nnew) if (lmalloc) then call self%copy(enc_temp) deallocate(enc_temp) end if else - self%status(nrequested+1:nold) = INACTIVE + self%status(nnew+1:nold) = INACTIVE end if - self%nenc = nrequested + self%nenc = nnew return end subroutine symba_util_resize_pltpenc diff --git a/src/util/util_append.f90 b/src/util/util_append.f90 index 3a5b3ba81..854220a89 100644 --- a/src/util/util_append.f90 +++ b/src/util/util_append.f90 @@ -15,7 +15,7 @@ module subroutine util_append_body(self, source, param, lsource_mask) logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to associate(nold => self%nbody, nnew => source%nbody) - if (nnew > size(self%status)) call self%resize(nnew, param) + if (nnew > size(self%status)) call self%resize(nnew) end associate return diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 index bc8cdcf43..b21f061f4 100644 --- a/src/util/util_copy.f90 +++ b/src/util/util_copy.f90 @@ -26,7 +26,7 @@ module subroutine util_copy_into_body(self, source, param, lsource_mask) lfill_list = .false. lfill_list(1:nnew) = .true. associate(nold => self%nbody) - if (nnew > size(self%status)) call self%resize(nnew, param) + if (nnew > size(self%status)) call self%resize(nnew) call self%fill(source, lfill_list) end associate return diff --git a/src/util/util_resize.f90 b/src/util/util_resize.f90 index 986053546..53df2bd73 100644 --- a/src/util/util_resize.f90 +++ b/src/util/util_resize.f90 @@ -1,40 +1,258 @@ submodule (swiftest_classes) s_util_resize use swiftest contains + module subroutine util_resize_arr_char_string(arr, nnew) + !! author: David A. Minton + !! + !! Resizes an array component of type character string. Array will only be resized if has previously been allocated. Passing 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 + ! Internals + character(len=STRMAX), dimension(:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold !! Old size + + if (.not. allocated(arr) .or. nnew < 0) return + + nold = size(arr) + if (nnew == nold) return + + if (nnew == 0) then + deallocate(arr) + return + end if + + allocate(tmp(nnew)) + if (nnew > nold) then + tmp(1:nold) = arr(1:nold) + else + tmp(1:nnew) = arr(1:nnew) + end if + call move_alloc(tmp, arr) + + return + end subroutine util_resize_arr_char_string + - module subroutine util_resize_body(self, nrequested, param) + module subroutine util_resize_arr_DP(arr, nnew) !! author: David A. Minton !! - !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + !! Resizes an array component of double precision type. Array will only be resized if has previously been allocated. 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 + ! Internals + real(DP), dimension(:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold !! Old size + + if (.not. allocated(arr) .or. nnew < 0) return + + nold = size(arr) + if (nnew == nold) return + + if (nnew == 0) then + deallocate(arr) + return + end if + + allocate(tmp(nnew)) + if (nnew > nold) then + tmp(1:nold) = arr(1:nold) + else + tmp(1:nnew) = arr(1:nnew) + end if + call move_alloc(tmp, arr) + + return + end subroutine util_resize_arr_DP + + + module subroutine util_resize_arr_DPvec(arr, nnew) + !! author: David A. Minton + !! + !! Resizes an array component of double precision vectors of size (NDIM, n). Array will only be resized if has previously been allocated. Passing nnew = 0 will deallocate. implicit none ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest body object - integer(I4B), intent(in) :: nrequested !! New size neded - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + real(DP), dimension(:,:), allocatable, intent(inout) :: arr !! Array to resize + integer(I4B), intent(in) :: nnew !! New size ! Internals - class(swiftest_body), allocatable :: temp - integer(I4B) :: nold - logical :: lmalloc + real(DP), dimension(:,:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold !! Old size - lmalloc = allocated(self%status) - if (lmalloc) then - nold = size(self%status) + if (.not. allocated(arr) .or. nnew < 0) return + + nold = size(arr, dim=2) + if (nnew == nold) return + + if (nnew == 0) then + deallocate(arr) + return + end if + + allocate(tmp(NDIM, nnew)) + if (nnew > nold) then + tmp(:, 1:nold) = arr(:, 1:nold) else - nold = 0 - end if - if (nrequested > nold) then - if (lmalloc) allocate(temp, source=self) - call self%setup(nrequested, param) - if (lmalloc) then - call self%copy_into(temp, param) - deallocate(temp) - end if + tmp(:, 1:nnew) = arr(:, 1:nnew) + end if + call move_alloc(tmp, arr) + + return + end subroutine util_resize_arr_DPvec + + + module subroutine util_resize_arr_I4B(arr, nnew) + !! author: David A. Minton + !! + !! Resizes an array component of integer type. Array will only be resized if has previously been allocated. 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 + ! Internals + integer(I4B), dimension(:), allocatable :: tmp !! Temporary storage array in case the input array is already allocated + integer(I4B) :: nold !! Old size + + if (.not. allocated(arr) .or. nnew < 0) return + + nold = size(arr) + if (nnew == nold) return + + if (nnew == 0) then + deallocate(arr) + return + end if + + allocate(tmp(nnew)) + if (nnew > nold) then + tmp(1:nold) = arr(1:nold) else - self%status(nrequested+1:nold) = INACTIVE + tmp(1:nnew) = arr(1:nnew) end if - self%nbody = nrequested + call move_alloc(tmp, arr) + + return + end subroutine util_resize_arr_I4B + + + module subroutine util_resize_arr_logical(arr, nnew) + !! author: David A. Minton + !! + !! Resizes an array component of logical type. Array will only be resized if has previously been allocated. Passing nnew = 0 will deallocate. + implicit none + ! Arguments + 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 + + if (.not. allocated(arr) .or. nnew < 0) return + + nold = size(arr) + if (nnew == nold) return + + if (nnew == 0) then + deallocate(arr) + return + end if + + allocate(tmp(nnew)) + if (nnew > nold) then + tmp(1:nold) = arr(1:nold) + else + tmp(1:nnew) = arr(1:nnew) + end if + call move_alloc(tmp, arr) + + return + end subroutine util_resize_arr_logical + + + module subroutine util_resize_body(self, nnew) + !! author: David A. Minton + !! + !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + implicit none + ! Arguments + class(swiftest_body), intent(inout) :: self !! Swiftest body object + integer(I4B), intent(in) :: nnew !! New size neded + + call util_resize(self%name, nnew) + call util_resize(self%status, nnew) + call util_resize(self%ldiscard, nnew) + call util_resize(self%lmask, nnew) + call util_resize(self%mu, nnew) + call util_resize(self%xh, nnew) + call util_resize(self%vh, nnew) + call util_resize(self%xb, nnew) + call util_resize(self%vb, nnew) + call util_resize(self%ah, nnew) + call util_resize(self%aobl, nnew) + call util_resize(self%atide, nnew) + call util_resize(self%agr, nnew) + call util_resize(self%ir3h, nnew) + call util_resize(self%a, nnew) + call util_resize(self%e, nnew) + call util_resize(self%inc, nnew) + call util_resize(self%capom, nnew) + call util_resize(self%omega, nnew) + call util_resize(self%capm, nnew) + self%nbody = count(self%status(1:nnew) == ACTIVE) return end subroutine util_resize_body + + module subroutine util_resize_pl(self, nnew) + !! author: David A. Minton + !! + !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + implicit none + ! Arguments + class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object + integer(I4B), intent(in) :: nnew !! New size neded + + call util_resize_body(self, nnew) + + call util_resize(self%mass, nnew) + call util_resize(self%Gmass, nnew) + call util_resize(self%rhill, nnew) + call util_resize(self%radius, nnew) + call util_resize(self%xbeg, nnew) + call util_resize(self%xend, nnew) + call util_resize(self%vbeg, nnew) + call util_resize(self%density, nnew) + call util_resize(self%Ip, nnew) + call util_resize(self%rot, nnew) + call util_resize(self%k2, nnew) + call util_resize(self%Q, nnew) + call util_resize(self%tlag, nnew) + call self%eucl_index() + + return + end subroutine util_resize_pl + + + module subroutine util_resize_tp(self, nnew) + !! author: David A. Minton + !! + !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + implicit none + ! Arguments + class(swiftest_tp), intent(inout) :: self !! Swiftest massive body object + integer(I4B), intent(in) :: nnew !! New size neded + + call util_resize_body(self, nnew) + + call util_resize(self%isperi, nnew) + call util_resize(self%peri, nnew) + call util_resize(self%atp, nnew) + + return + end subroutine util_resize_tp + + end submodule s_util_resize \ No newline at end of file diff --git a/src/whm/whm_util.f90 b/src/whm/whm_util.f90 index deb5dde5a..c0f3a021b 100644 --- a/src/whm/whm_util.f90 +++ b/src/whm/whm_util.f90 @@ -69,6 +69,27 @@ module subroutine whm_util_fill_pl(self, inserts, lfill_list) end subroutine whm_util_fill_pl + module subroutine whm_util_resize_pl(self, nnew) + !! author: David A. Minton + !! + !! Checks the current size of a massive body against the requested size and resizes it if it is too small. + implicit none + ! Arguments + class(whm_pl), intent(inout) :: self !! WHM massive body object + integer(I4B), intent(in) :: nnew !! New size neded + + call util_resize_pl(self, nnew) + + call util_resize(self%eta, nnew) + call util_resize(self%xj, nnew) + call util_resize(self%vj, nnew) + call util_resize(self%muj, nnew) + call util_resize(self%ir3j, nnew) + + return + end subroutine whm_util_resize_pl + + module subroutine whm_util_set_ir3j(self) !! author: David A. Minton !! From 4372de700365915b8d3a181927dac58b434a53b5 Mon Sep 17 00:00:00 2001 From: David Minton Date: Mon, 2 Aug 2021 09:12:56 -0400 Subject: [PATCH 11/42] Removed unnecessary copy_into method --- src/modules/swiftest_classes.f90 | 9 -------- src/util/util_copy.f90 | 35 -------------------------------- 2 files changed, 44 deletions(-) delete mode 100644 src/util/util_copy.f90 diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 00802f3fa..47d66ee51 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -165,7 +165,6 @@ module swiftest_classes procedure :: setup => setup_body !! A constructor that sets the number of bodies and allocates all allocatable arrays procedure :: accel_user => user_kick_getacch_body !! Add user-supplied heliocentric accelerations to planets procedure :: append => util_append_body !! Appends elements from one structure to another - procedure :: copy_into => util_copy_into_body !! Copies elements from one Swiftest body object to another. procedure :: fill => util_fill_body !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => 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 => util_set_ir3h !! Sets the inverse heliocentric radius term (1/rh**3) @@ -770,14 +769,6 @@ module subroutine util_coord_h2b_tp(self, cb) class(swiftest_cb), intent(in) :: cb !! Swiftest central body object end subroutine util_coord_h2b_tp - module subroutine util_copy_into_body(self, source, param, lsource_mask) - implicit none - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(in) :: source !! Source object to append - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to - end subroutine util_copy_into_body - module subroutine util_exit(code) implicit none integer(I4B), intent(in) :: code !! Failure exit code diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 deleted file mode 100644 index b21f061f4..000000000 --- a/src/util/util_copy.f90 +++ /dev/null @@ -1,35 +0,0 @@ -submodule (swiftest_classes) s_util_copy - use swiftest -contains - - module subroutine util_copy_into_body(self, source, param, lsource_mask) - !! author: David A. Minton - !! - !! Copies elements from one Swiftest body object to another. - !! This method will automatically resize the destination body if it is too small - implicit none - ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(in) :: source !! Source object to append - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to - ! Internals - integer(I4B) :: i,nnew - logical, dimension(:), allocatable :: lfill_list - - if (present(lsource_mask)) then - nnew = count(lsource_mask) - else - nnew = size(source%status) - end if - allocate(lfill_list(size(self%status))) - lfill_list = .false. - lfill_list(1:nnew) = .true. - associate(nold => self%nbody) - if (nnew > size(self%status)) call self%resize(nnew) - call self%fill(source, lfill_list) - end associate - return - end subroutine util_copy_into_body - -end submodule s_util_copy \ No newline at end of file From cedfc4c46c851c7716d9ce67a69857f03f7657c1 Mon Sep 17 00:00:00 2001 From: David Minton Date: Mon, 2 Aug 2021 09:43:34 -0400 Subject: [PATCH 12/42] Added beginnings of an append method that SyMBA will use to make add and subtract lists --- src/modules/swiftest_classes.f90 | 42 +++++++- src/util/util_append.f90 | 179 ++++++++++++++++++++++++++++++- 2 files changed, 216 insertions(+), 5 deletions(-) diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 47d66ee51..7501d730c 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -736,12 +736,50 @@ module subroutine user_kick_getacch_body(self, system, param, t, lbeg) 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 user_kick_getacch_body + end interface + + interface util_append + module subroutine util_append_arr_char_string(arr, source, lsource_mask) + implicit none + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr !! Destination array + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine util_append_arr_char_string + + module subroutine util_append_arr_DP(arr, source, lsource_mask) + implicit none + real(DP), dimension(:), allocatable, intent(inout) :: arr !! Destination array + real(DP), dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine util_append_arr_DP + + module subroutine util_append_arr_DPvec(arr, source, lsource_mask) + implicit none + real(DP), dimension(:,:), allocatable, intent(inout) :: arr !! Destination array + real(DP), dimension(:,:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine util_append_arr_DPvec - module subroutine util_append_body(self, source, param, lsource_mask) + module subroutine util_append_arr_I4B(arr, source, lsource_mask) + implicit none + integer(I4B), dimension(:), allocatable, intent(inout) :: arr !! Destination array + integer(I4B), dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine util_append_arr_I4B + + module subroutine util_append_arr_logical(arr, source, lsource_mask) + implicit none + logical, dimension(:), allocatable, intent(inout) :: arr !! Destination array + logical, dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine util_append_arr_logical + end interface + + interface + module subroutine 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 - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_append_body diff --git a/src/util/util_append.f90 b/src/util/util_append.f90 index 854220a89..4d9948641 100644 --- a/src/util/util_append.f90 +++ b/src/util/util_append.f90 @@ -2,7 +2,182 @@ use swiftest contains - module subroutine util_append_body(self, source, param, lsource_mask) + module subroutine util_append_arr_char_string(arr, source, 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. + implicit none + ! Arguments + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr !! Destination array + character(len=STRMAX), dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B) :: narr, nsrc + + if (.not. allocated(source)) return + + if (present(lsource_mask)) then + nsrc = count(lsource_mask) + else + nsrc = size(source) + end if + + if (allocated(arr)) then + narr = size(arr) + else + allocate(arr(nsrc)) + narr = 0 + end if + + call util_resize(arr, narr+nsrc) + + arr(narr+1:nsrc) = source(:) + + return + end subroutine util_append_arr_char_string + + + module subroutine util_append_arr_DP(arr, source, 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. + implicit none + ! Arguments + real(DP), dimension(:), allocatable, intent(inout) :: arr !! Destination array + real(DP), dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B) :: narr, nsrc + + if (.not. allocated(source)) return + + if (present(lsource_mask)) then + nsrc = count(lsource_mask) + else + nsrc = size(source) + end if + + if (allocated(arr)) then + narr = size(arr) + else + allocate(arr(nsrc)) + narr = 0 + end if + + call util_resize(arr, narr+nsrc) + + arr(narr+1:nsrc) = source(:) + + return + end subroutine util_append_arr_DP + + + module subroutine util_append_arr_DPvec(arr, source, 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. + implicit none + ! Arguments + real(DP), dimension(:,:), allocatable, intent(inout) :: arr !! Destination array + real(DP), dimension(:,:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B) :: narr, nsrc + + if (.not. allocated(source)) return + + if (present(lsource_mask)) then + nsrc = count(lsource_mask) + else + nsrc = size(source, dim=2) + end if + + if (allocated(arr)) then + narr = size(arr, dim=2) + else + allocate(arr(NDIM,nsrc)) + narr = 0 + end if + + call util_resize(arr, narr+nsrc) + + arr(:,narr+1:nsrc) = source(:,:) + + return + end subroutine util_append_arr_DPvec + + + module subroutine util_append_arr_I4B(arr, source, 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. + implicit none + ! Arguments + integer(I4B), dimension(:), allocatable, intent(inout) :: arr !! Destination array + integer(I4B), dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B) :: narr, nsrc + + if (.not. allocated(source)) return + + if (present(lsource_mask)) then + nsrc = count(lsource_mask) + else + nsrc = size(source) + end if + + if (allocated(arr)) then + narr = size(arr) + else + allocate(arr(nsrc)) + narr = 0 + end if + + call util_resize(arr, narr+nsrc) + + arr(narr+1:nsrc) = source(:) + + return + end subroutine util_append_arr_I4B + + + module subroutine util_append_arr_logical(arr, source, 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. + implicit none + ! Arguments + logical, dimension(:), allocatable, intent(inout) :: arr !! Destination array + logical, dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B) :: narr, nsrc + + if (.not. allocated(source)) return + + if (present(lsource_mask)) then + nsrc = count(lsource_mask) + else + nsrc = size(source) + end if + + if (allocated(arr)) then + narr = size(arr) + else + allocate(arr(nsrc)) + narr = 0 + end if + + call util_resize(arr, narr+nsrc) + + arr(narr+1:nsrc) = source(:) + + return + end subroutine util_append_arr_logical + + + module subroutine util_append_body(self, source, lsource_mask) !! author: David A. Minton !! !! Append components from one Swiftest body object to another. @@ -11,11 +186,9 @@ module subroutine util_append_body(self, source, param, lsource_mask) ! Arguments class(swiftest_body), intent(inout) :: self !! Swiftest body object class(swiftest_body), intent(in) :: source !! Source object to append - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to associate(nold => self%nbody, nnew => source%nbody) - if (nnew > size(self%status)) call self%resize(nnew) end associate return From f4bce42975db7d9a27f6040dfbe42e2d980f86e3 Mon Sep 17 00:00:00 2001 From: David Minton Date: Mon, 2 Aug 2021 12:16:05 -0400 Subject: [PATCH 13/42] Added append methods to all body types --- src/modules/rmvs_classes.f90 | 18 +++ src/modules/swiftest_classes.f90 | 52 ++++++--- src/modules/symba_classes.f90 | 40 ++++++- src/modules/whm_classes.f90 | 27 +++-- src/rmvs/rmvs_util.f90 | 69 +++++++++++- src/symba/symba_util.f90 | 144 +++++++++++++++++++++++- src/util/util_append.f90 | 182 ++++++++++++++++++++++++------- src/util/util_exit.f90 | 1 + src/whm/whm_util.f90 | 85 ++++++++++----- 9 files changed, 514 insertions(+), 104 deletions(-) diff --git a/src/modules/rmvs_classes.f90 b/src/modules/rmvs_classes.f90 index 49794b1ef..315b098a8 100644 --- a/src/modules/rmvs_classes.f90 +++ b/src/modules/rmvs_classes.f90 @@ -71,6 +71,7 @@ module rmvs_classes procedure :: accel => rmvs_kick_getacch_tp !! Calculates either the standard or modified version of the acceleration depending if the !! if the test particle is undergoing a close encounter or not procedure :: setup => rmvs_setup_tp !! Constructor method - Allocates space for number of particles + procedure :: append => rmvs_util_append_tp !! Appends elements from one structure to another procedure :: fill => rmvs_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => rmvs_util_resize_tp !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => rmvs_util_sort_tp !! Sorts body arrays by a sortable componen @@ -93,6 +94,7 @@ module rmvs_classes logical :: lplanetocentric = .false. !! Flag that indicates that the object is a planetocentric set of masive bodies used for close encounter calculations contains procedure :: setup => rmvs_setup_pl !! Constructor method - Allocates space for number of particles + procedure :: append => rmvs_util_append_pl !! Appends elements from one structure to another procedure :: fill => rmvs_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => rmvs_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => rmvs_util_sort_pl !! Sorts body arrays by a sortable componen @@ -156,6 +158,22 @@ module subroutine rmvs_setup_tp(self, n, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parametere end subroutine rmvs_setup_tp + module subroutine rmvs_util_append_pl(self, source, lsource_mask) + use swiftest_classes, only : swiftest_body + implicit none + class(rmvs_pl), intent(inout) :: self !! RMVS massive body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine rmvs_util_append_pl + + module subroutine rmvs_util_append_tp(self, source, lsource_mask) + use swiftest_classes, only : swiftest_body + implicit none + class(rmvs_tp), intent(inout) :: self !! RMVS test particle object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine rmvs_util_append_tp + module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 7501d730c..c7a7939a1 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -205,6 +205,7 @@ module swiftest_classes procedure :: accel_obl => obl_acc_pl !! Compute the barycentric accelerations of bodies due to the oblateness of the central body procedure :: setup => 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 => util_append_pl !! Appends elements from one structure to another procedure :: h2b => util_coord_h2b_pl !! Convert massive bodies from heliocentric to barycentric coordinates (position and velocity) procedure :: b2h => util_coord_b2h_pl !! Convert massive bodies from barycentric to heliocentric coordinates (position and velocity) procedure :: fill => util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) @@ -231,19 +232,20 @@ module swiftest_classes contains ! Test particle-specific concrete methods ! These are concrete because they are the same implemenation for all integrators - procedure :: discard => discard_tp !! Check to see if test particles should be discarded based on their positions relative to the massive bodies - procedure :: accel_int => kick_getacch_int_tp !! Compute direct cross (third) term heliocentric accelerations of test particles by massive bodies - procedure :: accel_obl => obl_acc_tp !! Compute the barycentric accelerations of bodies due to the oblateness of the central body - procedure :: setup => setup_tp !! A base constructor that sets the number of bodies and - procedure :: h2b => util_coord_h2b_tp !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) - procedure :: b2h => util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) - procedure :: fill => util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) - procedure :: get_peri => util_peri_tp !! Determine system pericenter passages for test particles - procedure :: resize => 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 => util_set_mu_tp !! Method used to construct the vectorized form of the central body mass - procedure :: sort => util_sort_tp !! Sorts body arrays by a sortable component - procedure :: rearrange => util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods - procedure :: spill => util_spill_tp !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: discard => discard_tp !! Check to see if test particles should be discarded based on their positions relative to the massive bodies + procedure :: accel_int => kick_getacch_int_tp !! Compute direct cross (third) term heliocentric accelerations of test particles by massive bodies + procedure :: accel_obl => obl_acc_tp !! Compute the barycentric accelerations of bodies due to the oblateness of the central body + procedure :: setup => setup_tp !! A base constructor that sets the number of bodies and + procedure :: append => util_append_tp !! Appends elements from one structure to another + procedure :: h2b => util_coord_h2b_tp !! Convert test particles from heliocentric to barycentric coordinates (position and velocity) + procedure :: b2h => util_coord_b2h_tp !! Convert test particles from barycentric to heliocentric coordinates (position and velocity) + procedure :: fill => util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: get_peri => util_peri_tp !! Determine system pericenter passages for test particles + procedure :: resize => 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 => util_set_mu_tp !! Method used to construct the vectorized form of the central body mass + procedure :: sort => util_sort_tp !! Sorts body arrays by a sortable component + procedure :: rearrange => util_sort_rearrange_tp !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods + procedure :: 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 !******************************************************************************************************************************** @@ -742,35 +744,35 @@ end subroutine user_kick_getacch_body module subroutine util_append_arr_char_string(arr, source, lsource_mask) implicit none character(len=STRMAX), dimension(:), allocatable, intent(inout) :: arr !! Destination array - character(len=STRMAX), dimension(:), allocatable, intent(inout) :: source !! Array to append + character(len=STRMAX), dimension(:), allocatable, intent(in) :: source !! Array to append logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_append_arr_char_string module subroutine util_append_arr_DP(arr, source, lsource_mask) implicit none real(DP), dimension(:), allocatable, intent(inout) :: arr !! Destination array - real(DP), dimension(:), allocatable, intent(inout) :: source !! Array to append + real(DP), dimension(:), allocatable, intent(in) :: source !! Array to append logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_append_arr_DP module subroutine util_append_arr_DPvec(arr, source, lsource_mask) implicit none real(DP), dimension(:,:), allocatable, intent(inout) :: arr !! Destination array - real(DP), dimension(:,:), allocatable, intent(inout) :: source !! Array to append + real(DP), dimension(:,:), allocatable, intent(in) :: source !! Array to append logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_append_arr_DPvec module subroutine util_append_arr_I4B(arr, source, lsource_mask) implicit none integer(I4B), dimension(:), allocatable, intent(inout) :: arr !! Destination array - integer(I4B), dimension(:), allocatable, intent(inout) :: source !! Array to append + integer(I4B), dimension(:), allocatable, intent(in) :: source !! Array to append logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_append_arr_I4B module subroutine util_append_arr_logical(arr, source, lsource_mask) implicit none logical, dimension(:), allocatable, intent(inout) :: arr !! Destination array - logical, dimension(:), allocatable, intent(inout) :: source !! Array to append + logical, dimension(:), allocatable, intent(in) :: source !! Array to append logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_append_arr_logical end interface @@ -783,6 +785,20 @@ module subroutine util_append_body(self, source, lsource_mask) logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine util_append_body + module subroutine 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(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine util_append_pl + + module subroutine 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(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine util_append_tp + module subroutine util_coord_b2h_pl(self, cb) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 712b98f65..01af9a48f 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -92,6 +92,7 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_pl !! Checks if massive bodies are going through close encounters with each other procedure :: accel => symba_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies procedure :: setup => symba_setup_pl !! Constructor method - Allocates space for number of particle + procedure :: append => symba_util_append_pl !! Appends elements from one structure to another procedure :: fill => symba_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => symba_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => symba_util_sort_pl !! Sorts body arrays by a sortable componen @@ -112,6 +113,7 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_tp !! Checks if any test particles are undergoing a close encounter with a massive body procedure :: accel => symba_kick_getacch_tp !! Compute heliocentric accelerations of test particles procedure :: setup => symba_setup_tp !! Constructor method - Allocates space for number of particle + procedure :: append => symba_util_append_tp !! Appends elements from one structure to another procedure :: fill => symba_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => symba_util_resize_tp !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => symba_util_sort_tp !! Sorts body arrays by a sortable componen @@ -419,6 +421,40 @@ module subroutine symba_step_reset_system(self) implicit none class(symba_nbody_system), intent(inout) :: self !! SyMBA nbody system object end subroutine symba_step_reset_system + end interface + + interface util_append + module subroutine symba_util_append_arr_info(arr, source, lsource_mask) + implicit none + type(symba_particle_info), dimension(:), allocatable, intent(inout) :: arr !! Destination array + type(symba_particle_info), dimension(:), allocatable, intent(in) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine symba_util_append_arr_info + + module subroutine symba_util_append_arr_kin(arr, source, lsource_mask) + implicit none + type(symba_kinship), dimension(:), allocatable, intent(inout) :: arr !! Destination array + type(symba_kinship), dimension(:), allocatable, intent(in) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine symba_util_append_arr_kin + end interface + + interface + module subroutine symba_util_append_pl(self, source, lsource_mask) + use swiftest_classes, only : swiftest_body + implicit none + class(symba_pl), intent(inout) :: self !! SyMBA massive body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine symba_util_append_pl + + module subroutine symba_util_append_tp(self, source, lsource_mask) + use swiftest_classes, only : swiftest_body + implicit none + class(symba_tp), intent(inout) :: self !! SyMBA test particle object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine symba_util_append_tp module subroutine symba_util_copy_pltpenc(self, source) implicit none @@ -434,12 +470,12 @@ end subroutine symba_util_copy_plplenc end interface interface util_fill - module subroutine symba_util_fill_arr_char_info(keeps, inserts, lfill_list) + module subroutine symba_util_fill_arr_info(keeps, inserts, lfill_list) implicit none type(symba_particle_info), dimension(:), allocatable, intent(inout) :: keeps !! Array of values to keep type(symba_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 symba_util_fill_arr_char_info + end subroutine symba_util_fill_arr_info module subroutine symba_util_fill_arr_kin(keeps, inserts, lfill_list) implicit none diff --git a/src/modules/whm_classes.f90 b/src/modules/whm_classes.f90 index 0f67c9432..e581e52b1 100644 --- a/src/modules/whm_classes.f90 +++ b/src/modules/whm_classes.f90 @@ -38,6 +38,7 @@ module whm_classes procedure :: gr_pos_kick => whm_gr_p4_pl !! Position kick due to p**4 term in the post-Newtonian correction procedure :: accel => whm_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies procedure :: kick => whm_kick_vh_pl !! Kick heliocentric velocities of massive bodies + procedure :: append => whm_util_append_pl !! Appends elements from one structure to another procedure :: fill => whm_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => whm_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: set_ir3 => whm_util_set_ir3j !! Sets both the heliocentric and jacobi inverse radius terms (1/rj**3 and 1/rh**3) @@ -207,6 +208,15 @@ module subroutine whm_step_pl(self, system, param, t, dt) real(DP), intent(in) :: dt !! Current stepsize end subroutine whm_step_pl + module subroutine whm_step_system(self, param, t, dt) + use swiftest_classes, only : swiftest_parameters + implicit none + class(whm_nbody_system), intent(inout) :: self !! WHM 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 whm_step_system + module subroutine whm_step_tp(self, system, param, t, dt) use swiftest_classes, only : swiftest_nbody_system, swiftest_parameters implicit none @@ -217,6 +227,14 @@ module subroutine whm_step_tp(self, system, param, t, dt) real(DP), intent(in) :: dt !! Stepsize end subroutine whm_step_tp + module subroutine whm_util_append_pl(self, source, lsource_mask) + use swiftest_classes, only : swiftest_body + implicit none + class(whm_pl), intent(inout) :: self !! WHM massive body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine whm_util_append_pl + module subroutine whm_util_spill_pl(self, discards, lspill_list, ldestructive) use swiftest_classes, only : swiftest_body implicit none @@ -226,15 +244,6 @@ module subroutine whm_util_spill_pl(self, discards, lspill_list, ldestructive) logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine whm_util_spill_pl - module subroutine whm_step_system(self, param, t, dt) - use swiftest_classes, only : swiftest_parameters - implicit none - class(whm_nbody_system), intent(inout) :: self !! WHM 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 whm_step_system - module subroutine whm_util_fill_pl(self, inserts, lfill_list) use swiftest_classes, only : swiftest_body implicit none diff --git a/src/rmvs/rmvs_util.f90 b/src/rmvs/rmvs_util.f90 index dcf0de473..8f0d7cf5d 100644 --- a/src/rmvs/rmvs_util.f90 +++ b/src/rmvs/rmvs_util.f90 @@ -2,6 +2,66 @@ use swiftest contains + module subroutine rmvs_util_append_pl(self, source, lsource_mask) + !! author: David A. Minton + !! + !! Append components from one massive body object to another. + !! This method will automatically resize the destination body if it is too small + implicit none + !! Arguments + class(rmvs_pl), intent(inout) :: self !! RMVS massive body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + + select type(source) + class is (rmvs_pl) + call util_append(self%nenc, source%nenc, lsource_mask) + call util_append(self%tpenc1P, source%tpenc1P, lsource_mask) + call util_append(self%plind, source%plind, lsource_mask) + + ! The following are not implemented as RMVS doesn't make use of fill operations on pl type + ! So they are here as a placeholder in case someone wants to extend the RMVS class for some reason + !call util_append(self%outer, source%outer, lsource_mask) + !call util_append(self%inner, source%inner, lsource_mask) + !call util_append(self%planetocentric, source%planetocentric, lsource_mask) + + call whm_util_append_pl(self, source, lsource_mask) + class default + write(*,*) "Invalid object passed to the append method. Source must be of class rmvs_pl or its descendents" + call util_exit(FAILURE) + end select + + return + end subroutine rmvs_util_append_pl + + + module subroutine rmvs_util_append_tp(self, source, lsource_mask) + !! author: David A. Minton + !! + !! Append components from test particle object to another. + !! This method will automatically resize the destination body if it is too small + implicit none + !! Arguments + class(rmvs_tp), intent(inout) :: self !! RMVS test particle object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + + select type(source) + class is (rmvs_tp) + call util_append(self%lperi, source%lperi, lsource_mask) + call util_append(self%plperP, source%plperP, lsource_mask) + call util_append(self%plencP, source%plencP, lsource_mask) + + call util_append_tp(self, source, lsource_mask) ! Note: whm_tp does not have its own append method, so we skip back to the base class + class default + write(*,*) "Invalid object passed to the append method. Source must be of class rmvs_tp or its descendents" + call util_exit(FAILURE) + end select + + return + end subroutine rmvs_util_append_tp + + module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) !! author: David A. Minton !! @@ -19,11 +79,16 @@ module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) associate(keeps => self) select type(inserts) class is (rmvs_pl) - call util_fill(keeps%nenc, inserts%nenc, lfill_list) call util_fill(keeps%tpenc1P, inserts%tpenc1P, lfill_list) call util_fill(keeps%plind, inserts%plind, lfill_list) + ! The following are not implemented as RMVS doesn't make use of fill operations on pl type + ! So they are here as a placeholder in case someone wants to extend the RMVS class for some reason + !call util_fill(keeps%outer, inserts%outer, lfill_list) + !call util_fill(keeps%inner, inserts%inner, lfill_list) + !call util_fill(keeps%planetocentric, inserts%planetocentric, lfill_list) + call whm_util_fill_pl(keeps, inserts, lfill_list) class default write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' @@ -53,7 +118,7 @@ module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) call util_fill(keeps%plperP, inserts%plperP, lfill_list) call util_fill(keeps%plencP, inserts%plencP, lfill_list) - call util_fill_tp(keeps, inserts, lfill_list) + call util_fill_tp(keeps, inserts, lfill_list) ! Note: whm_tp does not have its own fill method, so we skip back to the base class class default write(*,*) 'Error! fill method called for incompatible return type on rmvs_tp' end select diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index f2f72d12d..02d839bb2 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -2,6 +2,142 @@ use swiftest contains + module subroutine symba_util_append_arr_info(arr, source, lsource_mask) + !! author: David A. Minton + !! + !! Append a single array of particle information type onto another. If the destination array is not allocated, or is not big enough, this will allocate space for it. + implicit none + ! Arguments + type(symba_particle_info), dimension(:), allocatable, intent(inout) :: arr !! Destination array + type(symba_particle_info), dimension(:), allocatable, intent(in) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B) :: narr, nsrc + + if (.not. allocated(source)) return + + if (present(lsource_mask)) then + nsrc = count(lsource_mask) + else + nsrc = size(source) + end if + + if (allocated(arr)) then + narr = size(arr) + else + allocate(arr(nsrc)) + narr = 0 + end if + + if (present(lsource_mask)) then + arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + else + arr(narr+1:nsrc) = source(:) + end if + + return + end subroutine symba_util_append_arr_info + + + module subroutine symba_util_append_arr_kin(arr, source, lsource_mask) + !! author: David A. Minton + !! + !! Append a single array of kinship type onto another. If the destination array is not allocated, or is not big enough, this will allocate space for it. + implicit none + ! Arguments + type(symba_kinship), dimension(:), allocatable, intent(inout) :: arr !! Destination array + type(symba_kinship), dimension(:), allocatable, intent(in) :: source !! Array to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B) :: narr, nsrc + + if (.not. allocated(source)) return + + if (present(lsource_mask)) then + nsrc = count(lsource_mask) + else + nsrc = size(source) + end if + + if (allocated(arr)) then + narr = size(arr) + else + allocate(arr(nsrc)) + narr = 0 + end if + + if (present(lsource_mask)) then + arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + else + arr(narr+1:nsrc) = source(:) + end if + + return + end subroutine symba_util_append_arr_kin + + + module subroutine symba_util_append_pl(self, source, lsource_mask) + !! author: David A. Minton + !! + !! Append components from one massive body object to another. + !! 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(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + + select type(source) + class is (symba_pl) + call util_append(self%lcollision, source%lcollision, lsource_mask) + call util_append(self%lencounter, source%lencounter, lsource_mask) + call util_append(self%lmtiny, source%lmtiny, lsource_mask) + call util_append(self%nplenc, source%nplenc, lsource_mask) + call util_append(self%ntpenc, source%ntpenc, lsource_mask) + call util_append(self%levelg, source%levelg, lsource_mask) + call util_append(self%levelm, source%levelm, lsource_mask) + call util_append(self%isperi, source%isperi, lsource_mask) + call util_append(self%peri, source%peri, lsource_mask) + call util_append(self%atp, source%atp, lsource_mask) + call util_append(self%kin, source%kin, lsource_mask) + call util_append(self%info, source%info, lsource_mask) + + call 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 + class default + write(*,*) "Invalid object passed to the append method. Source must be of class symba_pl or its descendents" + call util_exit(FAILURE) + end select + + return + end subroutine symba_util_append_pl + + + module subroutine symba_util_append_tp(self, source, lsource_mask) + !! author: David A. Minton + !! + !! Append components from test particle object to another. + !! 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(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + + select type(source) + class is (symba_tp) + call util_append(self%nplenc, source%nplenc, lsource_mask) + call util_append(self%levelg, source%levelg, lsource_mask) + call util_append(self%levelm, source%levelm, lsource_mask) + + call 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 + class default + write(*,*) "Invalid object passed to the append method. Source must be of class symba_tp or its descendents" + call util_exit(FAILURE) + end select + + return + end subroutine symba_util_append_tp + module subroutine symba_util_copy_pltpenc(self, source) !! author: David A. Minton !! @@ -48,7 +184,7 @@ module subroutine symba_util_copy_plplenc(self, source) end subroutine symba_util_copy_plplenc - module subroutine symba_util_fill_arr_char_info(keeps, inserts, lfill_list) + module subroutine symba_util_fill_arr_info(keeps, inserts, lfill_list) !! author: David A. Minton !! !! Performs a fill operation on a single array of particle origin information types @@ -65,7 +201,7 @@ module subroutine symba_util_fill_arr_char_info(keeps, inserts, lfill_list) keeps(:) = unpack(inserts(:), lfill_list(:), keeps(:)) return - end subroutine symba_util_fill_arr_char_info + end subroutine symba_util_fill_arr_info module subroutine symba_util_fill_arr_kin(keeps, inserts, lfill_list) @@ -116,7 +252,7 @@ module subroutine symba_util_fill_pl(self, inserts, lfill_list) call util_fill(keeps%kin, inserts%kin, lfill_list) call util_fill(keeps%info, inserts%info, lfill_list) - call util_fill_pl(keeps, inserts, lfill_list) + call 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 class default write(*,*) 'Error! fill method called for incompatible return type on symba_pl' end select @@ -145,7 +281,7 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) call util_fill(keeps%levelg, inserts%levelg, lfill_list) call util_fill(keeps%levelm, inserts%levelm, lfill_list) - call util_fill_tp(keeps, inserts, lfill_list) + call 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 class default write(*,*) 'Error! fill method called for incompatible return type on symba_tp' end select diff --git a/src/util/util_append.f90 b/src/util/util_append.f90 index 4d9948641..0ca112eb9 100644 --- a/src/util/util_append.f90 +++ b/src/util/util_append.f90 @@ -8,9 +8,9 @@ module subroutine util_append_arr_char_string(arr, source, lsource_mask) !! 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(inout) :: source !! Array to append - logical, dimension(:), optional, intent(in) :: 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 + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: narr, nsrc @@ -29,9 +29,11 @@ module subroutine util_append_arr_char_string(arr, source, lsource_mask) narr = 0 end if - call util_resize(arr, narr+nsrc) - - arr(narr+1:nsrc) = source(:) + if (present(lsource_mask)) then + arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + else + arr(narr+1:nsrc) = source(:) + end if return end subroutine util_append_arr_char_string @@ -43,9 +45,9 @@ module subroutine util_append_arr_DP(arr, source, lsource_mask) !! 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(inout) :: source !! Array to append - logical, dimension(:), optional, intent(in) :: 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 + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: narr, nsrc @@ -64,9 +66,11 @@ module subroutine util_append_arr_DP(arr, source, lsource_mask) narr = 0 end if - call util_resize(arr, narr+nsrc) - - arr(narr+1:nsrc) = source(:) + if (present(lsource_mask)) then + arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + else + arr(narr+1:nsrc) = source(:) + end if return end subroutine util_append_arr_DP @@ -78,9 +82,9 @@ module subroutine util_append_arr_DPvec(arr, source, lsource_mask) !! 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(inout) :: source !! Array to append - logical, dimension(:), optional, intent(in) :: 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 + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: narr, nsrc @@ -95,13 +99,17 @@ module subroutine util_append_arr_DPvec(arr, source, lsource_mask) if (allocated(arr)) then narr = size(arr, dim=2) else - allocate(arr(NDIM,nsrc)) + allocate(arr(NDIM, nsrc)) narr = 0 end if - call util_resize(arr, narr+nsrc) - - arr(:,narr+1:nsrc) = source(:,:) + if (present(lsource_mask)) then + arr(1, narr+1:nsrc) = pack(source(1,:), lsource_mask(:)) + arr(2, narr+1:nsrc) = pack(source(2,:), lsource_mask(:)) + arr(3, narr+1:nsrc) = pack(source(3,:), lsource_mask(:)) + else + arr(:, narr+1:nsrc) = source(:,:) + end if return end subroutine util_append_arr_DPvec @@ -113,9 +121,9 @@ module subroutine util_append_arr_I4B(arr, source, lsource_mask) !! 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(inout) :: source !! Array to append - logical, dimension(:), optional, intent(in) :: 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 + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: narr, nsrc @@ -134,9 +142,12 @@ module subroutine util_append_arr_I4B(arr, source, lsource_mask) narr = 0 end if - call util_resize(arr, narr+nsrc) + if (present(lsource_mask)) then + arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + else + arr(narr+1:nsrc) = source(:) + end if - arr(narr+1:nsrc) = source(:) return end subroutine util_append_arr_I4B @@ -148,20 +159,14 @@ module subroutine util_append_arr_logical(arr, source, lsource_mask) !! 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(inout) :: source !! Array to append - logical, dimension(:), optional, intent(in) :: 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 + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to ! Internals integer(I4B) :: narr, nsrc if (.not. allocated(source)) return - if (present(lsource_mask)) then - nsrc = count(lsource_mask) - else - nsrc = size(source) - end if - if (allocated(arr)) then narr = size(arr) else @@ -169,9 +174,17 @@ module subroutine util_append_arr_logical(arr, source, lsource_mask) narr = 0 end if - call util_resize(arr, narr+nsrc) + if (present(lsource_mask)) then + nsrc = count(lsource_mask) + else + nsrc = size(source) + end if - arr(narr+1:nsrc) = source(:) + if (present(lsource_mask)) then + arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + else + arr(narr+1:nsrc) = source(:) + end if return end subroutine util_append_arr_logical @@ -184,14 +197,101 @@ module subroutine util_append_body(self, source, lsource_mask) !! This method will automatically resize the destination body if it is too small implicit none ! Arguments - class(swiftest_body), intent(inout) :: self !! Swiftest body object - class(swiftest_body), intent(in) :: source !! Source object to append - logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to - - associate(nold => self%nbody, nnew => source%nbody) + class(swiftest_body), intent(inout) :: self !! Swiftest body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + + call util_append(self%name, source%name, lsource_mask) + call util_append(self%status, source%status, lsource_mask) + call util_append(self%ldiscard, source%ldiscard, lsource_mask) + call util_append(self%lmask, source%lmask, lsource_mask) + call util_append(self%mu, source%mu, lsource_mask) + call util_append(self%xh, source%xh, lsource_mask) + call util_append(self%vh, source%vh, lsource_mask) + call util_append(self%xb, source%xb, lsource_mask) + call util_append(self%vb, source%vb, lsource_mask) + call util_append(self%ah, source%ah, lsource_mask) + call util_append(self%aobl, source%aobl, lsource_mask) + call util_append(self%atide, source%atide, lsource_mask) + call util_append(self%agr, source%agr, lsource_mask) + call util_append(self%ir3h, source%ir3h, lsource_mask) + call util_append(self%a, source%a, lsource_mask) + call util_append(self%e, source%e, lsource_mask) + call util_append(self%inc, source%inc, lsource_mask) + call util_append(self%capom, source%capom, lsource_mask) + call util_append(self%omega, source%omega, lsource_mask) + call util_append(self%capm, source%capm, lsource_mask) + + self%nbody = count(self%status(:) == ACTIVE) - end associate return end subroutine util_append_body + + module subroutine util_append_pl(self, source, lsource_mask) + !! author: David A. Minton + !! + !! Append components from one Swiftest body object to another. + !! This method will automatically resize the destination body if it is too small + implicit none + ! Arguments + class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + + + select type(source) + class is (swiftest_pl) + call util_append(self%mass, source%mass, lsource_mask) + call util_append(self%Gmass, source%Gmass, lsource_mask) + call util_append(self%rhill, source%rhill, lsource_mask) + call util_append(self%radius, source%radius, lsource_mask) + call util_append(self%xbeg, source%xbeg, lsource_mask) + call util_append(self%xend, source%xend, lsource_mask) + call util_append(self%vbeg, source%vbeg, lsource_mask) + call util_append(self%density, source%density, lsource_mask) + call util_append(self%Ip, source%Ip, lsource_mask) + call util_append(self%rot, source%rot, lsource_mask) + call util_append(self%k2, source%k2, lsource_mask) + call util_append(self%Q, source%Q, lsource_mask) + call util_append(self%tlag, source%tlag, lsource_mask) + + call util_append_body(self, source, lsource_mask) + + call self%eucl_index() + class default + write(*,*) "Invalid object passed to the append method. Source must be of class swiftest_pl or its descendents" + call util_exit(FAILURE) + end select + + return + end subroutine util_append_pl + + + module subroutine util_append_tp(self, source, lsource_mask) + !! author: David A. Minton + !! + !! Append components from one Swiftest body object to another. + !! This method will automatically resize the destination body if it is too small + implicit none + ! Arguments + class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + + select type(source) + class is (swiftest_tp) + call util_append(self%isperi, source%isperi, lsource_mask) + call util_append(self%peri, source%peri, lsource_mask) + call util_append(self%atp, source%atp, lsource_mask) + + call util_append_body(self, source, lsource_mask) + class default + write(*,*) "Invalid object passed to the append method. Source must be of class swiftest_tp or its descendents" + call util_exit(FAILURE) + end select + + return + end subroutine util_append_tp + end submodule s_util_append \ No newline at end of file diff --git a/src/util/util_exit.f90 b/src/util/util_exit.f90 index 6814b0029..e770c10f5 100644 --- a/src/util/util_exit.f90 +++ b/src/util/util_exit.f90 @@ -26,6 +26,7 @@ module subroutine util_exit(code) case default write(*, FAIL_MSG) VERSION_NUMBER write(*, BAR) + error stop end select stop diff --git a/src/whm/whm_util.f90 b/src/whm/whm_util.f90 index c0f3a021b..5a095192c 100644 --- a/src/whm/whm_util.f90 +++ b/src/whm/whm_util.f90 @@ -2,38 +2,33 @@ use swiftest contains - module subroutine whm_util_spill_pl(self, discards, lspill_list, ldestructive) + module subroutine whm_util_append_pl(self, source, lsource_mask) !! author: David A. Minton !! - !! Move spilled (discarded) WHM test particle structure from active list to discard list - !! - !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 + !! Append components from one massive body object to another. + !! This method will automatically resize the destination body if it is too small implicit none - ! Arguments - class(whm_pl), intent(inout) :: self !! WHM 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 - ! Internals - integer(I4B) :: i - associate(keeps => self) - select type(discards) - class is (whm_pl) - call util_spill(keeps%eta, discards%eta, lspill_list, ldestructive) - call util_spill(keeps%muj, discards%muj, lspill_list, ldestructive) - call util_spill(keeps%ir3j, discards%ir3j, lspill_list, ldestructive) - call util_spill(keeps%xj, discards%xj, lspill_list, ldestructive) - call util_spill(keeps%vj, discards%vj, lspill_list, ldestructive) - - call util_spill_pl(keeps, discards, lspill_list, ldestructive) - class default - write(*,*) 'Error! spill method called for incompatible return type on whm_pl' - end select - end associate + !! Arguments + class(whm_pl), intent(inout) :: self !! WHM massive body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + + select type(source) + class is (whm_pl) + call util_append(self%eta, source%eta, lsource_mask) + call util_append(self%muj, source%muj, lsource_mask) + call util_append(self%ir3j, source%ir3j, lsource_mask) + call util_append(self%xj, source%xj, lsource_mask) + call util_append(self%vj, source%vj, lsource_mask) + + call util_append_pl(self, source, lsource_mask) + class default + write(*,*) "Invalid object passed to the append method. Source must be of class whm_pl or its descendents" + call util_exit(FAILURE) + end select return - end subroutine whm_util_spill_pl - + end subroutine whm_util_append_pl module subroutine whm_util_fill_pl(self, inserts, lfill_list) !! author: David A. Minton @@ -61,7 +56,8 @@ module subroutine whm_util_fill_pl(self, inserts, lfill_list) call util_fill_pl(keeps, inserts, lfill_list) class default - write(*,*) 'Error! fill method called for incompatible return type on whm_pl' + write(*,*) "Invalid object passed to the fill method. Inserts must be of class whm_pl or its descendents" + call util_exit(FAILURE) end select end associate @@ -186,5 +182,38 @@ module subroutine whm_util_sort_rearrange_pl(self, ind) return end subroutine whm_util_sort_rearrange_pl + + + module subroutine whm_util_spill_pl(self, discards, lspill_list, ldestructive) + !! author: David A. Minton + !! + !! Move spilled (discarded) WHM test particle structure from active list to discard list + !! + !! Adapted from David E. Kaufmann's Swifter routine whm_discard_spill.f90 + implicit none + ! Arguments + class(whm_pl), intent(inout) :: self !! WHM 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 + ! Internals + integer(I4B) :: i + associate(keeps => self) + select type(discards) + class is (whm_pl) + call util_spill(keeps%eta, discards%eta, lspill_list, ldestructive) + call util_spill(keeps%muj, discards%muj, lspill_list, ldestructive) + call util_spill(keeps%ir3j, discards%ir3j, lspill_list, ldestructive) + call util_spill(keeps%xj, discards%xj, lspill_list, ldestructive) + call util_spill(keeps%vj, discards%vj, lspill_list, ldestructive) + + call util_spill_pl(keeps, discards, lspill_list, ldestructive) + class default + write(*,*) 'Error! spill method called for incompatible return type on whm_pl' + end select + end associate + + return + end subroutine whm_util_spill_pl end submodule s_whm_util From 1e7f96c582a07761c21c3b913b35d46de68a5862 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 12:27:35 -0400 Subject: [PATCH 14/42] Updated WHM example --- examples/whm_swifter_comparison/pl.swifter.in | 48 +++++++++---------- .../whm_swifter_comparison/pl.swiftest.in | 48 +++++++++---------- .../swiftest_vs_swifter.ipynb | 8 ++-- examples/whm_swifter_comparison/tp.swifter.in | 16 +++---- .../whm_swifter_comparison/tp.swiftest.in | 16 +++---- 5 files changed, 68 insertions(+), 68 deletions(-) diff --git a/examples/whm_swifter_comparison/pl.swifter.in b/examples/whm_swifter_comparison/pl.swifter.in index 141e997da..946ff123b 100644 --- a/examples/whm_swifter_comparison/pl.swifter.in +++ b/examples/whm_swifter_comparison/pl.swifter.in @@ -2,35 +2,35 @@ 0 39.476926408897625196 0.0 0.0 0.0 0.0 0.0 0.0 -1 6.5537098095653139645e-06 0.0014751238438755500459 +1 6.5537098095653139645e-06 0.0014751242768086609319 1.6306381826061645943e-05 --0.065841771551149230746 0.30388831943526661838 0.030872485461978960153 --12.104810966946379345 -1.8005812017180330847 0.9632304211885714761 -2 9.663313399581537916e-05 0.006759080797928606587 +-0.21794225400065470044 0.24570059548519398995 0.040069659678364698274 +-9.768342370075118952 -6.4098488749322373205 0.37225116289830816995 +2 9.663313399581537916e-05 0.0067590742435367571566 4.0453784346544178454e-05 --0.65269716062695148917 -0.3065765656441301057 0.033456491497379246824 -3.0899533953493179043 -6.72112303206047562 -0.2705477431358893059 -3 0.000120026935827952453094 0.010044868190633438806 +-0.60413504586259936247 -0.39527613440541492507 0.029436881824798030033 +3.992938767473374092 -6.2169034295501688922 -0.3157349287333398891 +3 0.000120026935827952453094 0.010044891628501106769 4.25875607065040958e-05 -0.58046286084934750615 -0.8332000042504307258 3.7646553415201541957e-05 -5.053802748240266633 3.568560918001247615 -0.0001869334511378976778 -4 1.2739802010675941456e-05 0.0072467082986392815006 +0.6475137988388671717 -0.78146344078682306034 3.4954277703126252982e-05 +4.7364737841481480227 3.9858178826605781494 -0.000206181980282845843 +4 1.2739802010675941456e-05 0.0072466933032545104062 2.265740805092889601e-05 --1.5891417403740180081 0.4938480736359250889 0.049330990309104823244 --1.3261523862597792352 -4.4445327547884994806 -0.060612990482397517785 -5 0.037692251088985676735 0.3552707649709459117 +-1.6060166552595489531 0.43262604649099911658 0.048461907252935247647 +-1.1388942318608360441 -4.4988235352611598648 -0.066344559364066134143 +5 0.037692251088985676735 0.3552707368190505097 0.00046732617030490929307 -4.1148395833578952363 -2.8938323061728068453 -0.080043092204059404504 -1.5541304908644199467 2.386798324664287883 -0.044683660603562371893 -6 0.011285899820091272997 0.43765596788571493287 +4.1359946230316175786 -2.8610749953481979801 -0.08065244615734604161 +1.536603427793050461 2.399023353553466048 -0.044342472584791124157 +6 0.011285899820091272997 0.4376572328164372643 0.00038925687730393611812 -6.3589256477393849565 -7.653288021415167286 -0.12000977499446359442 -1.4556566113591374531 1.2999494788820976765 -0.08051428750367411639 -7 0.0017236589478267730203 0.46957663585116591335 +6.3788284394924916754 -7.635463758938534795 -0.121111501730720202974 +1.4521392831727842248 1.3041738917825064364 -0.08044788317293871613 +7 0.0017236589478267730203 0.46959013246222981483 0.00016953449859497231466 -14.816779495279050138 13.049265812461410263 -0.14351615042000470668 --0.9586068527340353378 1.013470229424341294 0.01613039934499510156 -8 0.0020336100526728302319 0.7813355837717117843 +14.803649648126269156 13.063133279359290029 -0.14329526741228329478 +-0.9596636872292902537 1.0125665712568530355 0.016140607193432704789 +8 0.0020336100526728302319 0.78135207839715916734 0.000164587904124493665 -29.564459991843019537 -4.5824598513731222837 -0.5870359532621901577 -0.1697807691732287658 1.1426067858222827636 -0.027409347819614317105 +29.566779964594630314 -4.5668176855665958414 -0.58741108465859714904 +0.16916723445783939828 1.142713652049310879 -0.027397346380668001207 diff --git a/examples/whm_swifter_comparison/pl.swiftest.in b/examples/whm_swifter_comparison/pl.swiftest.in index a5ed4ef1c..c13f0640d 100644 --- a/examples/whm_swifter_comparison/pl.swiftest.in +++ b/examples/whm_swifter_comparison/pl.swiftest.in @@ -1,33 +1,33 @@ 8 -1 6.5537098095653139645e-06 0.0014751238438755500459 +1 6.5537098095653139645e-06 0.0014751242768086609319 1.6306381826061645943e-05 --0.065841771551149230746 0.30388831943526661838 0.030872485461978960153 --12.104810966946379345 -1.8005812017180330847 0.9632304211885714761 -2 9.663313399581537916e-05 0.006759080797928606587 +-0.21794225400065470044 0.24570059548519398995 0.040069659678364698274 +-9.768342370075118952 -6.4098488749322373205 0.37225116289830816995 +2 9.663313399581537916e-05 0.0067590742435367571566 4.0453784346544178454e-05 --0.65269716062695148917 -0.3065765656441301057 0.033456491497379246824 -3.0899533953493179043 -6.72112303206047562 -0.2705477431358893059 -3 0.000120026935827952453094 0.010044868190633438806 +-0.60413504586259936247 -0.39527613440541492507 0.029436881824798030033 +3.992938767473374092 -6.2169034295501688922 -0.3157349287333398891 +3 0.000120026935827952453094 0.010044891628501106769 4.25875607065040958e-05 -0.58046286084934750615 -0.8332000042504307258 3.7646553415201541957e-05 -5.053802748240266633 3.568560918001247615 -0.0001869334511378976778 -4 1.2739802010675941456e-05 0.0072467082986392815006 +0.6475137988388671717 -0.78146344078682306034 3.4954277703126252982e-05 +4.7364737841481480227 3.9858178826605781494 -0.000206181980282845843 +4 1.2739802010675941456e-05 0.0072466933032545104062 2.265740805092889601e-05 --1.5891417403740180081 0.4938480736359250889 0.049330990309104823244 --1.3261523862597792352 -4.4445327547884994806 -0.060612990482397517785 -5 0.037692251088985676735 0.3552707649709459117 +-1.6060166552595489531 0.43262604649099911658 0.048461907252935247647 +-1.1388942318608360441 -4.4988235352611598648 -0.066344559364066134143 +5 0.037692251088985676735 0.3552707368190505097 0.00046732617030490929307 -4.1148395833578952363 -2.8938323061728068453 -0.080043092204059404504 -1.5541304908644199467 2.386798324664287883 -0.044683660603562371893 -6 0.011285899820091272997 0.43765596788571493287 +4.1359946230316175786 -2.8610749953481979801 -0.08065244615734604161 +1.536603427793050461 2.399023353553466048 -0.044342472584791124157 +6 0.011285899820091272997 0.4376572328164372643 0.00038925687730393611812 -6.3589256477393849565 -7.653288021415167286 -0.12000977499446359442 -1.4556566113591374531 1.2999494788820976765 -0.08051428750367411639 -7 0.0017236589478267730203 0.46957663585116591335 +6.3788284394924916754 -7.635463758938534795 -0.121111501730720202974 +1.4521392831727842248 1.3041738917825064364 -0.08044788317293871613 +7 0.0017236589478267730203 0.46959013246222981483 0.00016953449859497231466 -14.816779495279050138 13.049265812461410263 -0.14351615042000470668 --0.9586068527340353378 1.013470229424341294 0.01613039934499510156 -8 0.0020336100526728302319 0.7813355837717117843 +14.803649648126269156 13.063133279359290029 -0.14329526741228329478 +-0.9596636872292902537 1.0125665712568530355 0.016140607193432704789 +8 0.0020336100526728302319 0.78135207839715916734 0.000164587904124493665 -29.564459991843019537 -4.5824598513731222837 -0.5870359532621901577 -0.1697807691732287658 1.1426067858222827636 -0.027409347819614317105 +29.566779964594630314 -4.5668176855665958414 -0.58741108465859714904 +0.16916723445783939828 1.142713652049310879 -0.027397346380668001207 diff --git a/examples/whm_swifter_comparison/swiftest_vs_swifter.ipynb b/examples/whm_swifter_comparison/swiftest_vs_swifter.ipynb index 7740f02c8..ef0a664c8 100644 --- a/examples/whm_swifter_comparison/swiftest_vs_swifter.ipynb +++ b/examples/whm_swifter_comparison/swiftest_vs_swifter.ipynb @@ -43,9 +43,9 @@ "output_type": "stream", "text": [ "Reading Swiftest file param.swiftest.in\n", - "Reading in time 1.001e+00\n", + "Reading in time 1.000e+00\n", "Creating Dataset\n", - "Successfully converted 1463 output frames.\n", + "Successfully converted 1462 output frames.\n", "Swiftest simulation data stored as xarray DataSet .ds\n" ] } @@ -107,7 +107,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -167,7 +167,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] diff --git a/examples/whm_swifter_comparison/tp.swifter.in b/examples/whm_swifter_comparison/tp.swifter.in index d4bba791e..22ca5a6ca 100644 --- a/examples/whm_swifter_comparison/tp.swifter.in +++ b/examples/whm_swifter_comparison/tp.swifter.in @@ -1,13 +1,13 @@ 4 101 -2.1778219831071528034 1.7945000787160070299 -0.344538568144980073 --2.4660672364316131263 2.6696516059587804457 0.5387135399929646282 +2.1437140623725170485 1.8307543455088179929 -0.33710883085786358393 +-2.5169991736250634084 2.6269266483088493027 0.54674712095669365287 102 -3.0442667013982411817 -0.9663926835590784803 0.40722457070173800897 -0.50161667633754136036 2.5842510880432738114 -1.8324318157740491254 +3.0507953356624089025 -0.9309107058567914761 0.38209550228666327998 +0.45214249601424874418 2.5995875558304815747 -1.8388641770977671949 103 --0.34517723265404320898 -3.1406497314215879868 0.72728042419722227496 -3.0867794854837949715 0.086392107735322389756 -0.14509697121440676101 +-0.30288545144121659103 -3.139125526168093927 0.7252151132548391166 +3.0919425994019995516 0.13633790246363267858 -0.15665049243950410883 104 --1.9619853530057589364 -0.98771442784664698067 0.2682528168870427776 -2.180176917968356245 -3.7664581464574479557 -0.15265740558307136673 +-1.9314729940131600827 -1.0389307897540689396 0.26607157142831372454 +2.2775049779995786108 -3.7157836040053666307 -0.16601542341215017115 diff --git a/examples/whm_swifter_comparison/tp.swiftest.in b/examples/whm_swifter_comparison/tp.swiftest.in index d4bba791e..22ca5a6ca 100644 --- a/examples/whm_swifter_comparison/tp.swiftest.in +++ b/examples/whm_swifter_comparison/tp.swiftest.in @@ -1,13 +1,13 @@ 4 101 -2.1778219831071528034 1.7945000787160070299 -0.344538568144980073 --2.4660672364316131263 2.6696516059587804457 0.5387135399929646282 +2.1437140623725170485 1.8307543455088179929 -0.33710883085786358393 +-2.5169991736250634084 2.6269266483088493027 0.54674712095669365287 102 -3.0442667013982411817 -0.9663926835590784803 0.40722457070173800897 -0.50161667633754136036 2.5842510880432738114 -1.8324318157740491254 +3.0507953356624089025 -0.9309107058567914761 0.38209550228666327998 +0.45214249601424874418 2.5995875558304815747 -1.8388641770977671949 103 --0.34517723265404320898 -3.1406497314215879868 0.72728042419722227496 -3.0867794854837949715 0.086392107735322389756 -0.14509697121440676101 +-0.30288545144121659103 -3.139125526168093927 0.7252151132548391166 +3.0919425994019995516 0.13633790246363267858 -0.15665049243950410883 104 --1.9619853530057589364 -0.98771442784664698067 0.2682528168870427776 -2.180176917968356245 -3.7664581464574479557 -0.15265740558307136673 +-1.9314729940131600827 -1.0389307897540689396 0.26607157142831372454 +2.2775049779995786108 -3.7157836040053666307 -0.16601542341215017115 From 26ed1c99f3158d986d4ed1bfe2c2534505d9d62a Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 12:42:43 -0400 Subject: [PATCH 15/42] Fixed bug where status flag was not set properly for test particles in planetocentric systems --- .../1pl_1tp_encounter/swiftest_vs_swifter.ipynb | 4 ++-- src/rmvs/rmvs_step.f90 | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/rmvs_swifter_comparison/1pl_1tp_encounter/swiftest_vs_swifter.ipynb b/examples/rmvs_swifter_comparison/1pl_1tp_encounter/swiftest_vs_swifter.ipynb index d9be0df4d..29dcf43aa 100644 --- a/examples/rmvs_swifter_comparison/1pl_1tp_encounter/swiftest_vs_swifter.ipynb +++ b/examples/rmvs_swifter_comparison/1pl_1tp_encounter/swiftest_vs_swifter.ipynb @@ -81,8 +81,8 @@ { "data": { "text/plain": [ - "[,\n", - " ]" + "[,\n", + " ]" ] }, "execution_count": 6, diff --git a/src/rmvs/rmvs_step.f90 b/src/rmvs/rmvs_step.f90 index 113b4d02f..74e6958c9 100644 --- a/src/rmvs/rmvs_step.f90 +++ b/src/rmvs/rmvs_step.f90 @@ -442,6 +442,7 @@ subroutine rmvs_make_planetocentric(param, cb, pl, tp) tpenci%cb_heliocentric = cb tpenci%ipleP = i tpenci%lmask(:) = .true. + tpenci%status(:) = ACTIVE ! Grab all the encountering test particles and convert them to a planetocentric frame tpenci%id(:) = pack(tp%id(:), encmask(:)) do j = 1, NDIM From fb9449ed921286b822f743e4898ef2725b765624 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 12:52:00 -0400 Subject: [PATCH 16/42] Updated error checks to halt execution if a bad object is passed to fill and spill methods --- .../swiftest_vs_swifter.ipynb | 4 ++-- src/rmvs/rmvs_util.f90 | 16 ++++++++++------ src/symba/symba_util.f90 | 16 ++++++++++------ src/whm/whm_util.f90 | 5 +++-- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/examples/helio_swifter_comparison/swiftest_vs_swifter.ipynb b/examples/helio_swifter_comparison/swiftest_vs_swifter.ipynb index 7f0b1d4b9..9a4c22cb1 100644 --- a/examples/helio_swifter_comparison/swiftest_vs_swifter.ipynb +++ b/examples/helio_swifter_comparison/swiftest_vs_swifter.ipynb @@ -43,9 +43,9 @@ "output_type": "stream", "text": [ "Reading Swiftest file param.swiftest.in\n", - "Reading in time 1.001e+00\n", + "Reading in time 1.000e+00\n", "Creating Dataset\n", - "Successfully converted 1463 output frames.\n", + "Successfully converted 1462 output frames.\n", "Swiftest simulation data stored as xarray DataSet .ds\n" ] } diff --git a/src/rmvs/rmvs_util.f90 b/src/rmvs/rmvs_util.f90 index 8f0d7cf5d..0ba86c7e8 100644 --- a/src/rmvs/rmvs_util.f90 +++ b/src/rmvs/rmvs_util.f90 @@ -27,7 +27,7 @@ module subroutine rmvs_util_append_pl(self, source, lsource_mask) call whm_util_append_pl(self, source, lsource_mask) class default - write(*,*) "Invalid object passed to the append method. Source must be of class rmvs_pl or its descendents" + write(*,*) "Invalid object passed to the append method. Source must be of class rmvs_pl or its descendents!" call util_exit(FAILURE) end select @@ -54,7 +54,7 @@ module subroutine rmvs_util_append_tp(self, source, lsource_mask) call util_append_tp(self, source, lsource_mask) ! Note: whm_tp does not have its own append method, so we skip back to the base class class default - write(*,*) "Invalid object passed to the append method. Source must be of class rmvs_tp or its descendents" + write(*,*) "Invalid object passed to the append method. Source must be of class rmvs_tp or its descendents!" call util_exit(FAILURE) end select @@ -91,7 +91,8 @@ module subroutine rmvs_util_fill_pl(self, inserts, lfill_list) call whm_util_fill_pl(keeps, inserts, lfill_list) class default - write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' + write(*,*) "Invalid object passed to the fill method. Source must be of class rmvs_pl or its descendents!" + call util_exit(FAILURE) end select end associate @@ -120,7 +121,8 @@ module subroutine rmvs_util_fill_tp(self, inserts, lfill_list) call util_fill_tp(keeps, inserts, lfill_list) ! Note: whm_tp does not have its own fill method, so we skip back to the base class class default - write(*,*) 'Error! fill method called for incompatible return type on rmvs_tp' + write(*,*) "Invalid object passed to the fill method. Source must be of class rmvs_tp or its descendents!" + call util_exit(FAILURE) end select end associate @@ -334,7 +336,8 @@ module subroutine rmvs_util_spill_pl(self, discards, lspill_list, ldestructive) call whm_util_spill_pl(keeps, discards, lspill_list, ldestructive) class default - write(*,*) 'Error! spill method called for incompatible return type on rmvs_pl' + write(*,*) "Invalid object passed to the spill method. Source must be of class rmvs_pl or its descendents!" + call util_exit(FAILURE) end select end associate @@ -366,7 +369,8 @@ module subroutine rmvs_util_spill_tp(self, discards, lspill_list, ldestructive) call util_spill_tp(keeps, discards, lspill_list, ldestructive) class default - write(*,*) 'Error! spill method called for incompatible return type on rmvs_tp' + write(*,*) "Invalid object passed to the spill method. Source must be of class rmvs_tp or its descendents!" + call util_exit(FAILURE) end select end associate diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 02d839bb2..4c4b74476 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -104,7 +104,7 @@ module subroutine symba_util_append_pl(self, source, lsource_mask) call 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 class default - write(*,*) "Invalid object passed to the append method. Source must be of class symba_pl or its descendents" + write(*,*) "Invalid object passed to the append method. Source must be of class symba_pl or its descendents!" call util_exit(FAILURE) end select @@ -131,7 +131,7 @@ module subroutine symba_util_append_tp(self, source, lsource_mask) call 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 class default - write(*,*) "Invalid object passed to the append method. Source must be of class symba_tp or its descendents" + write(*,*) "Invalid object passed to the append method. Source must be of class symba_tp or its descendents!" call util_exit(FAILURE) end select @@ -254,7 +254,8 @@ module subroutine symba_util_fill_pl(self, inserts, lfill_list) call 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 class default - write(*,*) 'Error! fill method called for incompatible return type on symba_pl' + write(*,*) "Invalid object passed to the fill method. Source must be of class symba_pl or its descendents!" + call util_exit(FAILURE) end select end associate @@ -283,7 +284,8 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) call 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 class default - write(*,*) 'Error! fill method called for incompatible return type on symba_tp' + write(*,*) "Invalid object passed to the fill method. Source must be of class symba_tp or its descendents!" + call util_exit(FAILURE) end select end associate @@ -691,7 +693,8 @@ module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) call util_spill_pl(keeps, discards, lspill_list, ldestructive) class default - write(*,*) 'Error! spill method called for incompatible return type on symba_pl' + write(*,*) "Invalid object passed to the spill method. Source must be of class symba_pl or its descendents!" + call util_exit(FAILURE) end select end associate @@ -724,7 +727,8 @@ module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) call util_spill_tp(keeps, discards, lspill_list, ldestructive) class default - write(*,*) 'Error! spill method called for incompatible return type on symba_pl' + write(*,*) "Invalid object passed to the spill method. Source must be of class symba_tp or its descendents!" + call util_exit(FAILURE) end select end associate diff --git a/src/whm/whm_util.f90 b/src/whm/whm_util.f90 index 5a095192c..4dbc81fb7 100644 --- a/src/whm/whm_util.f90 +++ b/src/whm/whm_util.f90 @@ -56,7 +56,7 @@ module subroutine whm_util_fill_pl(self, inserts, lfill_list) call util_fill_pl(keeps, inserts, lfill_list) class default - write(*,*) "Invalid object passed to the fill method. Inserts must be of class whm_pl or its descendents" + write(*,*) "Invalid object passed to the fill method. Inserts must be of class whm_pl or its descendents!" call util_exit(FAILURE) end select end associate @@ -209,7 +209,8 @@ module subroutine whm_util_spill_pl(self, discards, lspill_list, ldestructive) call util_spill_pl(keeps, discards, lspill_list, ldestructive) class default - write(*,*) 'Error! spill method called for incompatible return type on whm_pl' + write(*,*) "Invalid object passed to the spill method. Source must be of class whm_pl or its descendents!" + call util_exit(FAILURE) end select end associate From c8b0db961c02cfc8613c9b728680f39137b6c369 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 12:57:51 -0400 Subject: [PATCH 17/42] Fixed bad class selection in the symba_tp spill implementation --- src/symba/symba_util.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 4c4b74476..19ac9cd3f 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -720,7 +720,7 @@ module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) !> Spill all the common components associate(keeps => self) select type(discards) - class is (symba_pl) + class is (symba_tp) call util_spill(keeps%nplenc, discards%nplenc, lspill_list, ldestructive) call util_spill(keeps%levelg, discards%levelg, lspill_list, ldestructive) call util_spill(keeps%levelm, discards%levelm, lspill_list, ldestructive) From f40f7a1a67a9d8502be9eeeb9a7245a8da06536b Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 13:19:03 -0400 Subject: [PATCH 18/42] Started working on creating the mergesub_list structure when a pl-pl collision is detected --- .../1pl_1pl_encounter/swiftest_vs_swifter.ipynb | 8 ++++---- .../swiftest_symba_vs_swifter_symba.ipynb | 4 ++-- src/symba/symba_collision.f90 | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/swiftest_vs_swifter.ipynb b/examples/symba_swifter_comparison/1pl_1pl_encounter/swiftest_vs_swifter.ipynb index 34c978f58..69349f2a4 100644 --- a/examples/symba_swifter_comparison/1pl_1pl_encounter/swiftest_vs_swifter.ipynb +++ b/examples/symba_swifter_comparison/1pl_1pl_encounter/swiftest_vs_swifter.ipynb @@ -81,8 +81,8 @@ { "data": { "text/plain": [ - "[,\n", - " ]" + "[,\n", + " ]" ] }, "execution_count": 6, @@ -485,7 +485,7 @@ " nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan])\n", "Coordinates:\n", " id float64 100.0\n", - " * time (y) (time (y)) float64 0.0 0.0006845 0.001369 ... 0.1492 0.1499 0.1506
    • id
      ()
      float64
      100.0
      array(100.)
    • time (y)
      (time (y))
      float64
      0.0 0.0006845 ... 0.1499 0.1506
      array([0.      , 0.000684, 0.001369, ..., 0.149213, 0.149897, 0.150582])
  • " ], "text/plain": [ "\n", diff --git a/examples/symba_swifter_comparison/8pl_16tp_encounters/swiftest_symba_vs_swifter_symba.ipynb b/examples/symba_swifter_comparison/8pl_16tp_encounters/swiftest_symba_vs_swifter_symba.ipynb index b348d1f81..c3c42dd4f 100644 --- a/examples/symba_swifter_comparison/8pl_16tp_encounters/swiftest_symba_vs_swifter_symba.ipynb +++ b/examples/symba_swifter_comparison/8pl_16tp_encounters/swiftest_symba_vs_swifter_symba.ipynb @@ -591,8 +591,8 @@ "array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])\n", "Coordinates:\n", " * id (id) int64 101 102 103 104 105 106 107 ... 111 112 113 114 115 116\n", - " time float64 110.0" + " time float64 110.0" ], "text/plain": [ "\n", diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index d601e853a..218eb9274 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -46,16 +46,30 @@ module subroutine symba_collision_check_plplenc(self, system, param, t, dt, irec mtot = pl%Gmass(ind1(k)) + pl%Gmass(ind2(k)) lcollision(k) = symba_collision_check_one(xr(1), xr(2), xr(3), vr(1), vr(2), vr(3), mtot, rlim, dt, plplenc_list%lvdotr(k)) end do + deallocate(lmask) if (any(lcollision(:))) then + allocate(lmask(pl%nbody)) do k = 1, nplplenc - if (plplenc_list%status(k) /= COLLISION) cycle + if (.not.lcollision(k)) cycle + + ! Set this encounter as a collision and save the position and velocity vectors at the time of the collision plplenc_list%status(k) = COLLISION plplenc_list%xh1(:,k) = pl%xh(:,ind1(k)) plplenc_list%vb1(:,k) = pl%vb(:,ind1(k)) plplenc_list%xh2(:,k) = pl%xh(:,ind2(k)) plplenc_list%vb2(:,k) = pl%vb(:,ind2(k)) + + ! Check to see if either of these bodies has been involved with a collision before, and if so, make this a collisional family if (pl%lcollision(ind1(k)) .or. pl%lcollision(ind2(k))) call pl%make_family([ind1(k),ind2(k)]) + + ! Add any of the bodies that have *not* previously been involved in a collision to the subtraction list + lmask(:) = .false. + lmask(ind1(k)) = .not.pl%lcollision(ind1(k)) + lmask(ind2(k)) = .not.pl%lcollision(ind2(k)) + call system%mergesub_list%append(pl, lmask) + + ! Set the collision flag for these to bodies to true in case they become involved in another collision later in the step pl%lcollision(ind1(k)) = .true. pl%lcollision(ind2(k)) = .true. end do From 025cd22a8ce74d0afff7e43e917022496da45c5b Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 14:02:36 -0400 Subject: [PATCH 19/42] Started working on getting SyMBA to recognize pl-pl collisions --- src/symba/symba_collision.f90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 218eb9274..7c0a05c91 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -70,9 +70,10 @@ module subroutine symba_collision_check_plplenc(self, system, param, t, dt, irec call system%mergesub_list%append(pl, lmask) ! Set the collision flag for these to bodies to true in case they become involved in another collision later in the step - pl%lcollision(ind1(k)) = .true. - pl%lcollision(ind2(k)) = .true. + pl%lcollision([ind1(k), ind2(k)]) = .true. + pl%ldiscard([ind1(k), ind2(k)]) = .true. end do + end if end associate end select From cc48db22915d963fd86f68694ea373bf9145cb3c Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 15:47:58 -0400 Subject: [PATCH 20/42] Fixed up append method to properly resize as needed --- src/rmvs/rmvs_util.f90 | 8 +++---- src/symba/symba_setup.f90 | 2 -- src/symba/symba_step.f90 | 4 ++-- src/symba/symba_util.f90 | 20 +++++++++++------- src/util/util_append.f90 | 44 ++++++++++++++++++++++++--------------- src/util/util_resize.f90 | 1 + src/whm/whm_util.f90 | 4 ++-- 7 files changed, 48 insertions(+), 35 deletions(-) diff --git a/src/rmvs/rmvs_util.f90 b/src/rmvs/rmvs_util.f90 index 0ba86c7e8..9f9cf0037 100644 --- a/src/rmvs/rmvs_util.f90 +++ b/src/rmvs/rmvs_util.f90 @@ -15,6 +15,8 @@ module subroutine rmvs_util_append_pl(self, source, lsource_mask) select type(source) class is (rmvs_pl) + call whm_util_append_pl(self, source, lsource_mask) + call util_append(self%nenc, source%nenc, lsource_mask) call util_append(self%tpenc1P, source%tpenc1P, lsource_mask) call util_append(self%plind, source%plind, lsource_mask) @@ -24,8 +26,6 @@ module subroutine rmvs_util_append_pl(self, source, lsource_mask) !call util_append(self%outer, source%outer, lsource_mask) !call util_append(self%inner, source%inner, lsource_mask) !call util_append(self%planetocentric, source%planetocentric, lsource_mask) - - call whm_util_append_pl(self, source, lsource_mask) class default write(*,*) "Invalid object passed to the append method. Source must be of class rmvs_pl or its descendents!" call util_exit(FAILURE) @@ -48,11 +48,11 @@ module subroutine rmvs_util_append_tp(self, source, lsource_mask) select type(source) class is (rmvs_tp) + call util_append_tp(self, source, lsource_mask) ! Note: whm_tp does not have its own append method, so we skip back to the base class + call util_append(self%lperi, source%lperi, lsource_mask) call util_append(self%plperP, source%plperP, lsource_mask) call util_append(self%plencP, source%plencP, lsource_mask) - - call util_append_tp(self, source, lsource_mask) ! Note: whm_tp does not have its own append method, so we skip back to the base class class default write(*,*) "Invalid object passed to the append method. Source must be of class rmvs_tp or its descendents!" call util_exit(FAILURE) diff --git a/src/symba/symba_setup.f90 b/src/symba/symba_setup.f90 index dab92f3ca..f2c8e63dd 100644 --- a/src/symba/symba_setup.f90 +++ b/src/symba/symba_setup.f90 @@ -18,8 +18,6 @@ module subroutine symba_setup_initialize_system(self, param) ! Call parent method associate(system => self) call whm_setup_initialize_system(system, param) - call system%mergeadd_list%setup(1, param) - call system%mergesub_list%setup(1, param) call system%pltpenc_list%setup(0) call system%plplenc_list%setup(0) select type(pl => system%pl) diff --git a/src/symba/symba_step.f90 b/src/symba/symba_step.f90 index e8badd577..41e7a3a74 100644 --- a/src/symba/symba_step.f90 +++ b/src/symba/symba_step.f90 @@ -265,8 +265,8 @@ module subroutine symba_step_reset_system(self) pltpenc_list%nenc = 0 end if - mergeadd_list%nbody = 0 - mergesub_list%nbody = 0 + call mergeadd_list%resize(0) + call mergesub_list%resize(0) end select end select end associate diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 19ac9cd3f..bdfbea86c 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -29,10 +29,12 @@ module subroutine symba_util_append_arr_info(arr, source, lsource_mask) narr = 0 end if + call util_resize(arr, narr + nsrc) + if (present(lsource_mask)) then - arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + arr(narr + 1:narr + nsrc) = pack(source(:), lsource_mask(:)) else - arr(narr+1:nsrc) = source(:) + arr(narr + 1:narr + nsrc) = source(:) end if return @@ -66,10 +68,12 @@ module subroutine symba_util_append_arr_kin(arr, source, lsource_mask) narr = 0 end if + call util_resize(arr, narr + nsrc) + if (present(lsource_mask)) then - arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + arr(narr + 1:narr + nsrc) = pack(source(:), lsource_mask(:)) else - arr(narr+1:nsrc) = source(:) + arr(narr + 1:narr + nsrc) = source(:) end if return @@ -89,6 +93,8 @@ module subroutine symba_util_append_pl(self, source, lsource_mask) select type(source) class is (symba_pl) + call 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 + call util_append(self%lcollision, source%lcollision, lsource_mask) call util_append(self%lencounter, source%lencounter, lsource_mask) call util_append(self%lmtiny, source%lmtiny, lsource_mask) @@ -101,8 +107,6 @@ module subroutine symba_util_append_pl(self, source, lsource_mask) call util_append(self%atp, source%atp, lsource_mask) call util_append(self%kin, source%kin, lsource_mask) call util_append(self%info, source%info, lsource_mask) - - call 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 class default write(*,*) "Invalid object passed to the append method. Source must be of class symba_pl or its descendents!" call util_exit(FAILURE) @@ -125,11 +129,11 @@ module subroutine symba_util_append_tp(self, source, lsource_mask) select type(source) class is (symba_tp) + call 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 + call util_append(self%nplenc, source%nplenc, lsource_mask) call util_append(self%levelg, source%levelg, lsource_mask) call util_append(self%levelm, source%levelm, lsource_mask) - - call 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 class default write(*,*) "Invalid object passed to the append method. Source must be of class symba_tp or its descendents!" call util_exit(FAILURE) diff --git a/src/util/util_append.f90 b/src/util/util_append.f90 index 0ca112eb9..a13103cfa 100644 --- a/src/util/util_append.f90 +++ b/src/util/util_append.f90 @@ -29,10 +29,12 @@ module subroutine util_append_arr_char_string(arr, source, lsource_mask) narr = 0 end if + call util_resize(arr, narr + nsrc) + if (present(lsource_mask)) then - arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + arr(narr + 1:narr + nsrc) = pack(source(:), lsource_mask(:)) else - arr(narr+1:nsrc) = source(:) + arr(narr + 1:narr + nsrc) = source(:) end if return @@ -66,10 +68,12 @@ module subroutine util_append_arr_DP(arr, source, lsource_mask) narr = 0 end if + call util_resize(arr, narr + nsrc) + if (present(lsource_mask)) then - arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + arr(narr + 1:narr + nsrc) = pack(source(:), lsource_mask(:)) else - arr(narr+1:nsrc) = source(:) + arr(narr + 1:narr + nsrc) = source(:) end if return @@ -103,12 +107,14 @@ module subroutine util_append_arr_DPvec(arr, source, lsource_mask) narr = 0 end if + call util_resize(arr, narr + nsrc) + if (present(lsource_mask)) then - arr(1, narr+1:nsrc) = pack(source(1,:), lsource_mask(:)) - arr(2, narr+1:nsrc) = pack(source(2,:), lsource_mask(:)) - arr(3, narr+1:nsrc) = pack(source(3,:), lsource_mask(:)) + arr(1, narr + 1:narr + nsrc) = pack(source(1,:), lsource_mask(:)) + arr(2, narr + 1:narr + nsrc) = pack(source(2,:), lsource_mask(:)) + arr(3, narr + 1:narr + nsrc) = pack(source(3,:), lsource_mask(:)) else - arr(:, narr+1:nsrc) = source(:,:) + arr(:, narr + 1:narr + nsrc) = source(:,:) end if return @@ -142,13 +148,14 @@ module subroutine util_append_arr_I4B(arr, source, lsource_mask) narr = 0 end if + call util_resize(arr, narr + nsrc) + if (present(lsource_mask)) then - arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + arr(narr + 1:narr + nsrc) = pack(source(:), lsource_mask(:)) else - arr(narr+1:nsrc) = source(:) + arr(narr + 1:narr + nsrc) = source(:) end if - return end subroutine util_append_arr_I4B @@ -180,10 +187,12 @@ module subroutine util_append_arr_logical(arr, source, lsource_mask) nsrc = size(source) end if + call util_resize(arr, narr + nsrc) + if (present(lsource_mask)) then - arr(narr+1:nsrc) = pack(source(:), lsource_mask(:)) + arr(narr + 1:narr + nsrc) = pack(source(:), lsource_mask(:)) else - arr(narr+1:nsrc) = source(:) + arr(narr + 1:narr + nsrc) = source(:) end if return @@ -202,6 +211,7 @@ module subroutine util_append_body(self, source, lsource_mask) logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to call util_append(self%name, source%name, lsource_mask) + call util_append(self%id, source%id, lsource_mask) call util_append(self%status, source%status, lsource_mask) call util_append(self%ldiscard, source%ldiscard, lsource_mask) call util_append(self%lmask, source%lmask, lsource_mask) @@ -242,6 +252,8 @@ module subroutine util_append_pl(self, source, lsource_mask) select type(source) class is (swiftest_pl) + call util_append_body(self, source, lsource_mask) + call util_append(self%mass, source%mass, lsource_mask) call util_append(self%Gmass, source%Gmass, lsource_mask) call util_append(self%rhill, source%rhill, lsource_mask) @@ -256,8 +268,6 @@ module subroutine util_append_pl(self, source, lsource_mask) call util_append(self%Q, source%Q, lsource_mask) call util_append(self%tlag, source%tlag, lsource_mask) - call util_append_body(self, source, lsource_mask) - call self%eucl_index() class default write(*,*) "Invalid object passed to the append method. Source must be of class swiftest_pl or its descendents" @@ -281,11 +291,11 @@ module subroutine util_append_tp(self, source, lsource_mask) select type(source) class is (swiftest_tp) + call util_append_body(self, source, lsource_mask) + call util_append(self%isperi, source%isperi, lsource_mask) call util_append(self%peri, source%peri, lsource_mask) call util_append(self%atp, source%atp, lsource_mask) - - call util_append_body(self, source, lsource_mask) class default write(*,*) "Invalid object passed to the append method. Source must be of class swiftest_tp or its descendents" call util_exit(FAILURE) diff --git a/src/util/util_resize.f90 b/src/util/util_resize.f90 index 53df2bd73..4a84a003b 100644 --- a/src/util/util_resize.f90 +++ b/src/util/util_resize.f90 @@ -181,6 +181,7 @@ module subroutine util_resize_body(self, nnew) integer(I4B), intent(in) :: nnew !! New size neded call util_resize(self%name, nnew) + call util_resize(self%id, nnew) call util_resize(self%status, nnew) call util_resize(self%ldiscard, nnew) call util_resize(self%lmask, nnew) diff --git a/src/whm/whm_util.f90 b/src/whm/whm_util.f90 index 4dbc81fb7..f3dc15d3e 100644 --- a/src/whm/whm_util.f90 +++ b/src/whm/whm_util.f90 @@ -15,13 +15,13 @@ module subroutine whm_util_append_pl(self, source, lsource_mask) select type(source) class is (whm_pl) + call util_append_pl(self, source, lsource_mask) + call util_append(self%eta, source%eta, lsource_mask) call util_append(self%muj, source%muj, lsource_mask) call util_append(self%ir3j, source%ir3j, lsource_mask) call util_append(self%xj, source%xj, lsource_mask) call util_append(self%vj, source%vj, lsource_mask) - - call util_append_pl(self, source, lsource_mask) class default write(*,*) "Invalid object passed to the append method. Source must be of class whm_pl or its descendents" call util_exit(FAILURE) From 19be7d8a10ea54e2e684fcddb91d59b73687f175 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 16:43:52 -0400 Subject: [PATCH 21/42] Cleaned up discard io routines and started adding SyMBA-specific discard writer --- .../1pl_1pl_encounter/cb.swiftest.in | Bin 53 -> 80 bytes .../1pl_1pl_encounter/init_cond.py | 1 + .../1pl_1pl_encounter/param.swiftest.in | 3 +- .../1pl_1pl_encounter/pl.swifter.in | 2 +- .../1pl_1pl_encounter/pl.swiftest.in | Bin 228 -> 256 bytes .../1pl_1pl_encounter/tp.swiftest.in | Bin 2 -> 16 bytes python/swiftest/swiftest/io.py | 12 +++- src/io/io.f90 | 61 +++++++++------- src/modules/swiftest_classes.f90 | 11 +-- src/modules/symba_classes.f90 | 63 ++++++++++------- src/rmvs/rmvs_step.f90 | 4 +- src/symba/symba_io.f90 | 66 +++++++++++++++++- 12 files changed, 156 insertions(+), 67 deletions(-) diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/cb.swiftest.in b/examples/symba_swifter_comparison/1pl_1pl_encounter/cb.swiftest.in index 4c5d870405c9daad1d597cb1d3f2bd78a1b2227e..d0ae0ed15fe3ea8dd15557055a926fce3c60b59c 100644 GIT binary patch literal 80 ncmd;JKmZOP6NHU2HoW29>+AsI-}OJ>6US3*597mhVB-S-U7iOf literal 53 wcmW;Axe)*$3rbo3*74~+Eq5}gct*a?m%+)WyI1?iYw*UYD diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/init_cond.py b/examples/symba_swifter_comparison/1pl_1pl_encounter/init_cond.py index 7600320c2..20be5a433 100755 --- a/examples/symba_swifter_comparison/1pl_1pl_encounter/init_cond.py +++ b/examples/symba_swifter_comparison/1pl_1pl_encounter/init_cond.py @@ -173,6 +173,7 @@ print(f'ENC_OUT {swiftest_enc}') print(f'EXTRA_FORCE no') print(f'BIG_DISCARD no') +print(f'DISCARD_OUT discard.swiftest.out') print(f'ROTATION no') print(f'GR no') print(f'MU2KG {MU2KG}') diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/param.swiftest.in b/examples/symba_swifter_comparison/1pl_1pl_encounter/param.swiftest.in index 1866557b2..d44f4df0e 100644 --- a/examples/symba_swifter_comparison/1pl_1pl_encounter/param.swiftest.in +++ b/examples/symba_swifter_comparison/1pl_1pl_encounter/param.swiftest.in @@ -5,7 +5,7 @@ DT 0.0006844626967830253 CB_IN cb.swiftest.in PL_IN pl.swiftest.in TP_IN tp.swiftest.in -IN_TYPE ASCII +IN_TYPE REAL8 ISTEP_OUT 1 ISTEP_DUMP 1 BIN_OUT bin.swiftest.dat @@ -22,6 +22,7 @@ CHK_QMIN_RANGE 0.004650467260962157 1000.0 ENC_OUT enc.swiftest.dat EXTRA_FORCE no BIG_DISCARD no +DISCARD_OUT discard.swiftest.out ROTATION no GR no MU2KG 1.988409870698051e+30 diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/pl.swifter.in b/examples/symba_swifter_comparison/1pl_1pl_encounter/pl.swifter.in index 0eb21018b..9f0548fc1 100644 --- a/examples/symba_swifter_comparison/1pl_1pl_encounter/pl.swifter.in +++ b/examples/symba_swifter_comparison/1pl_1pl_encounter/pl.swifter.in @@ -1,5 +1,5 @@ 3 ! Planet input file generated using init_cond.py -1 39.47692640889762629 +1 39.476926408897625196 0.0 0.0 0.0 0.0 0.0 0.0 2 0.00012002693582795244940133 0.010044724833237892 diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/pl.swiftest.in b/examples/symba_swifter_comparison/1pl_1pl_encounter/pl.swiftest.in index 19c6d6e3a2436162bb5984e0ecb1cb9352cb223f..d8da7a92a44b1e9caa3907ead959cdec31e066cc 100644 GIT binary patch literal 256 zcmd;JU|?VZVi4c}VgVqA@l!y8KmZa0VF>tOuNl*S=&QyDdsK0lJi2<~#U*rILVhbs zIyBlY7vp7;bRcBDlutC@{W5v`KZ2`e<&?MB!PKu_Vy_x9sl|Sa{`cIZU5Rja3YkwR SWDH@mKPFMv^xXC_SUmurogOa$ literal 228 zcmZ9Gxe)^~30`5m% zX0lVQ37Yye{^|yd{X~mu+c^*|K`` Ygvg?I8#T=l^4}PjYzRwv=DU9V0CM9iPyhe` diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/tp.swiftest.in b/examples/symba_swifter_comparison/1pl_1pl_encounter/tp.swiftest.in index 573541ac9702dd3969c9bc859d2b91ec1f7e6e56..64bf92f74a457d2f4bc42798493db15cc3ab1008 100644 GIT binary patch literal 16 Ncmd;JKmZOP6953P01*HH literal 2 JcmXru0ssJP06PEx diff --git a/python/swiftest/swiftest/io.py b/python/swiftest/swiftest/io.py index 2dd4ef7b3..5782c6444 100644 --- a/python/swiftest/swiftest/io.py +++ b/python/swiftest/swiftest/io.py @@ -5,7 +5,7 @@ import sys import tempfile -newfeaturelist = ("FRAGMENTATION", "ROTATION", "TIDES", "ENERGY", "GR", "YARKOVSKY", "YORP" ) +newfeaturelist = ("FRAGMENTATION", "ROTATION", "TIDES", "ENERGY", "GR", "YARKOVSKY", "YORP") def real2float(realstr): """ @@ -279,6 +279,7 @@ def write_labeled_param(param, param_file_name): 'CB_IN', 'BIN_OUT', 'ENC_OUT', + 'DISCARD_OUT', 'CHK_QMIN', 'CHK_RMIN', 'CHK_RMAX', @@ -889,7 +890,7 @@ def swift2swifter(swift_param, plname="", tpname="", conversion_questions={}): swifter_param['ENC_OUT'] = input("ENC_OUT: Encounter file name: [enc.dat]> ") if swifter_param['ENC_OUT'] == '': swifter_param['ENC_OUT'] = "enc.dat" - + intxt = conversion_questions.get('EXTRA_FORCE', None) if not intxt: intxt = input("EXTRA_FORCE: Use additional user-specified force routines? (y/N)> ") @@ -1228,6 +1229,13 @@ def swifter2swiftest(swifter_param, plname="", tpname="", cbname="", conversion_ swiftest_param.pop('J2', None) swiftest_param.pop('J4', None) swiftest_param.pop('RHILL_PRESENT', None) + + swiftest_param['DISCARD_OUT'] = conversion_questions.get('DISCARD_OUT', '') + if not swiftest_param['DISCARD_OUT']: + swiftest_param['DISCARD_OUT'] = input("DISCARD_OUT: Discard file name: [discard.out]> ") + if swiftest_param['DISCARD_OUT'] == '': + swiftest_param['DISCARD_OUT'] = "discard.out" + swiftest_param['! VERSION'] = "Swiftest parameter file converted from Swifter" return swiftest_param diff --git a/src/io/io.f90 b/src/io/io.f90 index b424094eb..e3556b11c 100644 --- a/src/io/io.f90 +++ b/src/io/io.f90 @@ -99,7 +99,9 @@ module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg) param_value = io_get_token(line, ifirst, ilast, iostat) read(param_value, *) self%qmin_ahi case ("ENC_OUT") - self%encounter_file = param_value + self%enc_out = param_value + case ("DISCARD_OUT") + self%discard_out = param_value case ("EXTRA_FORCE") call io_toupper(param_value) if (param_value == "YES" .or. param_value == 'T') self%lextra_force = .true. @@ -225,9 +227,7 @@ module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg) write(*,*) "CHK_QMIN = ",self%qmin write(*,*) "CHK_QMIN_COORD = ",trim(adjustl(self%qmin_coord)) write(*,*) "CHK_QMIN_RANGE = ",self%qmin_alo, self%qmin_ahi - write(*,*) "ENC_OUT = ",trim(adjustl(self%encounter_file)) write(*,*) "EXTRA_FORCE = ",self%lextra_force - write(*,*) "BIG_DISCARD = ",self%lbig_discard write(*,*) "RHILL_PRESENT = ",self%lrhill_present write(*,*) "ROTATION = ", self%lrotation write(*,*) "TIDES = ", self%ltides @@ -235,6 +235,18 @@ module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg) write(*,*) "MU2KG = ",self%MU2KG write(*,*) "TU2S = ",self%TU2S write(*,*) "DU2M = ",self%DU2M + if (trim(adjustl(self%enc_out)) /= "") then + write(*,*) "ENC_OUT = ",trim(adjustl(self%enc_out)) + else + write(*,*) "! ENC_OUT not set: Encounters will not be recorded to file" + end if + if (trim(adjustl(self%discard_out)) /= "") then + write(*,*) "DISCARD_OUT = ",trim(adjustl(self%discard_out)) + write(*,*) "BIG_DISCARD = ",self%lbig_discard + else + write(*,*) "! DISCARD_OUT not set: Discards will not be recorded to file" + write(*,*) "! BIG_DISCARD = ",self%lbig_discard + end if if ((self%MU2KG < 0.0_DP) .or. (self%TU2S < 0.0_DP) .or. (self%DU2M < 0.0_DP)) then write(iomsg,*) 'Invalid unit conversion factor' @@ -317,7 +329,7 @@ module subroutine io_param_writer(self, unit, iotype, v_list, iostat, iomsg) write(param_name, Afmt) "OUT_FORM"; write(param_value, Afmt) trim(adjustl(param%out_form)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) write(param_name, Afmt) "OUT_STAT"; write(param_value, Afmt) "APPEND"; write(unit, Afmt) adjustl(param_name), adjustl(param_value) end if - write(param_name, Afmt) "ENC_OUT"; write(param_value, Afmt) trim(adjustl(param%encounter_file)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "ENC_OUT"; write(param_value, Afmt) trim(adjustl(param%enc_out)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) if (param%istep_dump > 0) then write(param_name, Afmt) "ISTEP_DUMP"; write(param_value, Ifmt) param%istep_dump; write(unit, Afmt) adjustl(param_name), adjustl(param_value) end if @@ -761,7 +773,7 @@ end subroutine io_read_param_in function io_read_encounter(t, name1, name2, mass1, mass2, radius1, radius2, & - xh1, xh2, vh1, vh2, encounter_file, out_type) result(ierr) + xh1, xh2, vh1, vh2, enc_out, out_type) result(ierr) !! author: David A. Minton !! !! Read close encounter data from input binary files @@ -773,7 +785,7 @@ function io_read_encounter(t, name1, name2, mass1, mass2, radius1, radius2, & integer(I4B), intent(out) :: name1, name2 real(DP), intent(out) :: t, mass1, mass2, radius1, radius2 real(DP), dimension(:), intent(out) :: xh1, xh2, vh1, vh2 - character(*), intent(in) :: encounter_file, out_type + character(*), intent(in) :: enc_out, out_type ! Result integer(I4B) :: ierr ! Internals @@ -782,7 +794,7 @@ function io_read_encounter(t, name1, name2, mass1, mass2, radius1, radius2, & integer(I4B), save :: iu = lun if (lfirst) then - open(unit = iu, file = encounter_file, status = 'OLD', form = 'UNFORMATTED', iostat = ierr) + open(unit = iu, file = enc_out, status = 'OLD', form = 'UNFORMATTED', iostat = ierr) if (ierr /= 0) then write(*, *) "Swiftest Error:" write(*, *) " unable to open binary encounter file" @@ -1046,31 +1058,27 @@ module subroutine io_write_discard(self, param) character(*), parameter :: PLNAMEFMT = '(I8, 2(1X, E23.16))' class(swiftest_body), allocatable :: pltemp - associate(t => param%t, discards => self%tp_discards, nsp => self%tp_discards%nbody, dxh => self%tp_discards%xh, dvh => self%tp_discards%vh, & - dname => self%tp_discards%id, dstatus => self%tp_discards%status) - + associate(tp_discards => self%tp_discards, nsp => self%tp_discards%nbody, pl => self%pl, npl => self%pl%nbody) + if (nsp == 0) return select case(param%out_stat) case('APPEND') - open(unit = LUN, file = param%outfile, status = 'OLD', position = 'APPEND', form = 'UNFORMATTED', iostat = ierr) + open(unit = LUN, file = param%discard_out, status = 'OLD', position = 'APPEND', form = 'FORMATTED', iostat = ierr) case('NEW', 'REPLACE', 'UNKNOWN') - open(unit = LUN, file = param%outfile, status = param%out_stat, form = 'UNFORMATTED', iostat = ierr) + open(unit = LUN, file = param%discard_out, status = param%out_stat, form = 'FORMATTED', iostat = ierr) case default write(*,*) 'Invalid status code for OUT_STAT: ',trim(adjustl(param%out_stat)) call util_exit(FAILURE) end select lfirst = .false. - if (param%lgr) call discards%pv2v(param) + if (param%lgr) call tp_discards%pv2v(param) - write(LUN, HDRFMT) t, nsp, param%lbig_discard + write(LUN, HDRFMT) param%t, nsp, param%lbig_discard do i = 1, nsp - write(LUN, NAMEFMT) sub, dname(i), dstatus(i) - write(LUN, VECFMT) dxh(1, i), dxh(2, i), dxh(3, i) - write(LUN, VECFMT) dvh(1, i), dvh(2, i), dvh(3, i) + write(LUN, NAMEFMT) sub, tp_discards%id(i), tp_discards%status(i) + write(LUN, VECFMT) tp_discards%xh(1, i), tp_discards%xh(2, i), tp_discards%xh(3, i) + write(LUN, VECFMT) tp_discards%vh(1, i), tp_discards%vh(2, i), tp_discards%vh(3, i) end do if (param%lbig_discard) then - associate(npl => self%pl%nbody, pl => self%pl, GMpl => self%pl%Gmass, & - Rpl => self%pl%radius, name => self%pl%id, xh => self%pl%xh) - if (param%lgr) then allocate(pltemp, source = pl) call pltemp%pv2v(param) @@ -1082,12 +1090,11 @@ module subroutine io_write_discard(self, param) write(LUN, NPLFMT) npl do i = 1, npl - write(LUN, PLNAMEFMT) name(i), GMpl(i), Rpl(i) - write(LUN, VECFMT) xh(1, i), xh(2, i), xh(3, i) + write(LUN, PLNAMEFMT) pl%id(i), pl%Gmass(i), pl%radius(i) + write(LUN, VECFMT) pl%xh(1, i), pl%xh(2, i), pl%xh(3, i) write(LUN, VECFMT) vh(1, i), vh(2, i), vh(3, i) end do deallocate(vh) - end associate end if close(LUN) end associate @@ -1097,7 +1104,7 @@ end subroutine io_write_discard module subroutine io_write_encounter(t, name1, name2, mass1, mass2, radius1, radius2, & - xh1, xh2, vh1, vh2, encounter_file, out_type) + xh1, xh2, vh1, vh2, enc_out, out_type) !! author: David A. Minton !! !! Write close encounter data to output binary files @@ -1110,16 +1117,16 @@ module subroutine io_write_encounter(t, name1, name2, mass1, mass2, radius1, rad integer(I4B), intent(in) :: name1, name2 real(DP), intent(in) :: t, mass1, mass2, radius1, radius2 real(DP), dimension(:), intent(in) :: xh1, xh2, vh1, vh2 - character(*), intent(in) :: encounter_file, out_type + character(*), intent(in) :: enc_out, out_type ! Internals logical , save :: lfirst = .true. integer(I4B), parameter :: lun = 30 integer(I4B) :: ierr integer(I4B), save :: iu = lun - open(unit = iu, file = encounter_file, status = 'OLD', position = 'APPEND', form = 'UNFORMATTED', iostat = ierr) + open(unit = iu, file = enc_out, status = 'OLD', position = 'APPEND', form = 'UNFORMATTED', iostat = ierr) if ((ierr /= 0) .and. lfirst) then - open(unit = iu, file = encounter_file, status = 'NEW', form = 'UNFORMATTED', iostat = ierr) + open(unit = iu, file = enc_out, status = 'NEW', form = 'UNFORMATTED', iostat = ierr) end if if (ierr /= 0) then write(*, *) "Swiftest Error:" diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index c7a7939a1..83514a2ab 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -38,7 +38,8 @@ module swiftest_classes character(STRMAX) :: qmin_coord = 'HELIO' !! Coordinate frame to use for qmin real(DP) :: qmin_alo = -1.0_DP !! Minimum semimajor axis for qmin real(DP) :: qmin_ahi = -1.0_DP !! Maximum semimajor axis for qmin - character(STRMAX) :: encounter_file = ENC_OUTFILE !! Name of output file for encounters + character(STRMAX) :: enc_out = "" !! Name of output file for encounters + character(STRMAX) :: discard_out = "" !! Name of output file for discards 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 @@ -277,8 +278,8 @@ module swiftest_classes ! Concrete classes that are common to the basic integrator (only test particles considered for discard) procedure :: discard => discard_system !! Perform a discard step on the system procedure :: dump => io_dump_system !! Dump the state of the system to a file - procedure :: read_frame => io_read_frame_system !! Append a frame of output data to file - procedure :: write_discard => io_write_discard !! Append a frame of output data to file + procedure :: read_frame => io_read_frame_system !! Read in a frame of input data from file + procedure :: write_discard => io_write_discard !! Write out information about discarded test particles procedure :: write_frame => io_write_frame_system !! Append a frame of output data to file procedure :: initialize => setup_initialize_system !! Initialize the system from input files procedure :: step_spin => tides_step_spin_system !! Steps the spins of the massive & central bodies due to tides. @@ -584,12 +585,12 @@ module subroutine io_toupper(string) end subroutine io_toupper module subroutine io_write_encounter(t, name1, name2, mass1, mass2, radius1, radius2, & - xh1, xh2, vh1, vh2, encounter_file, out_type) + xh1, xh2, vh1, vh2, enc_out, out_type) implicit none integer(I4B), intent(in) :: name1, name2 real(DP), intent(in) :: t, mass1, mass2, radius1, radius2 real(DP), dimension(:), intent(in) :: xh1, xh2, vh1, vh2 - character(*), intent(in) :: encounter_file, out_type + character(*), intent(in) :: enc_out, out_type end subroutine io_write_encounter module subroutine io_write_frame_body(self, iu, param) diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 01af9a48f..2094b533a 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -167,6 +167,7 @@ module symba_classes class(symba_pl), allocatable :: pl_discards !! Discarded test particle data structure integer(I4B) :: irec !! System recursion level contains + procedure :: write_discard => symba_io_write_discard !! Write out information about discarded and merged planets and test particles in SyMBA procedure :: initialize => symba_setup_initialize_system !! Performs SyMBA-specific initilization steps procedure :: step => symba_step_system !! Advance the SyMBA nbody system forward in time by one step procedure :: interp => symba_step_interp_system !! Perform an interpolation step on the SymBA nbody system @@ -265,34 +266,12 @@ module function symba_encounter_check_tp(self, system, dt, irec) result(lany_enc logical :: lany_encounter !! Returns true if there is at least one close encounter end function symba_encounter_check_tp - module subroutine symba_kick_getacch_pl(self, system, param, t, lbeg) - use swiftest_classes, only : swiftest_nbody_system, swiftest_parameters - implicit none - class(symba_pl), intent(inout) :: self !! SyMBA massive body particle data structure - class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! Current simulation time - logical, intent(in) :: lbeg !! Logical flag that determines whether or not this is the beginning or end of the step - end subroutine symba_kick_getacch_pl - - module subroutine symba_kick_getacch_tp(self, system, param, t, lbeg) - use swiftest_classes, only : swiftest_nbody_system, swiftest_parameters - implicit none - class(symba_tp), intent(inout) :: self !! SyMBA test particle data structure - class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! Current time - logical, intent(in) :: lbeg !! Logical flag that determines whether or not this is the beginning or end of the step - end subroutine symba_kick_getacch_tp - - module subroutine symba_kick_pltpenc(self, system, dt, irec, sgn) + module subroutine symba_io_write_discard(self, param) + use swiftest_classes, only : swiftest_parameters implicit none - class(symba_pltpenc), intent(in) :: self !! SyMBA pl-tp encounter list object - class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object - real(DP), intent(in) :: dt !! step size - integer(I4B), intent(in) :: irec !! Current recursion level - integer(I4B), intent(in) :: sgn !! sign to be applied to acceleration - end subroutine symba_kick_pltpenc + class(symba_nbody_system), intent(inout) :: self !! SyMBA nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + end subroutine symba_io_write_discard module subroutine symba_io_dump_particle_info(self, param, msg) use swiftest_classes, only : swiftest_parameters @@ -341,6 +320,36 @@ module subroutine symba_io_read_frame_info(self, iu, param, form, ierr) integer(I4B), intent(out) :: ierr !! Error code end subroutine symba_io_read_frame_info + module subroutine symba_kick_getacch_pl(self, system, param, t, lbeg) + use swiftest_classes, only : swiftest_nbody_system, swiftest_parameters + implicit none + class(symba_pl), intent(inout) :: self !! SyMBA massive body particle data structure + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + real(DP), intent(in) :: t !! Current simulation time + logical, intent(in) :: lbeg !! Logical flag that determines whether or not this is the beginning or end of the step + end subroutine symba_kick_getacch_pl + + module subroutine symba_kick_getacch_tp(self, system, param, t, lbeg) + use swiftest_classes, only : swiftest_nbody_system, swiftest_parameters + implicit none + class(symba_tp), intent(inout) :: self !! SyMBA test particle data structure + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + real(DP), intent(in) :: t !! Current time + logical, intent(in) :: lbeg !! Logical flag that determines whether or not this is the beginning or end of the step + end subroutine symba_kick_getacch_tp + + module subroutine symba_kick_pltpenc(self, system, dt, irec, sgn) + implicit none + class(symba_pltpenc), intent(in) :: self !! SyMBA pl-tp encounter list object + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + real(DP), intent(in) :: dt !! step size + integer(I4B), intent(in) :: irec !! Current recursion level + integer(I4B), intent(in) :: sgn !! sign to be applied to acceleration + end subroutine symba_kick_pltpenc + + module subroutine symba_io_write_frame_info(self, iu, param) use swiftest_classes, only : swiftest_parameters implicit none diff --git a/src/rmvs/rmvs_step.f90 b/src/rmvs/rmvs_step.f90 index 74e6958c9..0385aeecc 100644 --- a/src/rmvs/rmvs_step.f90 +++ b/src/rmvs/rmvs_step.f90 @@ -539,7 +539,7 @@ subroutine rmvs_peri_tp(tp, pl, t, dt, lfirst, inner_index, ipleP, param) call orbel_xv2aqt(mu, xpc(:, i), vpc(:, i), a, peri, capm, tperi) r2 = dot_product(xpc(:, i), xpc(:, i)) if ((abs(tperi) > FACQDT * dt) .or. (r2 > rhill2)) peri = sqrt(r2) - if (param%encounter_file /= "") then + if (param%enc_out /= "") then id1 = pl%id(ipleP) rpl = pl%radius(ipleP) xh1(:) = pl%inner(inner_index)%x(:, ipleP) @@ -548,7 +548,7 @@ subroutine rmvs_peri_tp(tp, pl, t, dt, lfirst, inner_index, ipleP, param) xh2(:) = xpc(:, i) + xh1(:) vh2(:) = xpc(:, i) + vh1(:) call io_write_encounter(t, id1, id2, mu, 0.0_DP, rpl, 0.0_DP, xh1(:), xh2(:), vh1(:), vh2(:), & - param%encounter_file, param%out_type) + param%enc_out, param%out_type) end if if (tp%lperi(i)) then if (peri < tp%peri(i)) then diff --git a/src/symba/symba_io.f90 b/src/symba/symba_io.f90 index 403204017..97e4ab3f6 100644 --- a/src/symba/symba_io.f90 +++ b/src/symba/symba_io.f90 @@ -207,7 +207,70 @@ module subroutine symba_io_read_frame_info(self, iu, param, form, ierr) ierr = 0 end subroutine symba_io_read_frame_info - + + + module subroutine symba_io_write_discard(self, param) + implicit none + class(symba_nbody_system), intent(inout) :: self !! SyMBA nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + integer(I4B), parameter :: LUN = 40 + integer(I4B) :: i, ierr + logical, save :: lfirst = .true. + real(DP), dimension(:,:), allocatable :: vh + character(*), parameter :: HDRFMT = '(E23.16, 1X, I8, 1X, L1)' + character(*), parameter :: NAMEFMT = '(A, 2(1X, I8))' + character(*), parameter :: VECFMT = '(3(E23.16, 1X))' + character(*), parameter :: NPLFMT = '(I8)' + character(*), parameter :: PLNAMEFMT = '(I8, 2(1X, E23.16))' + class(swiftest_body), allocatable :: pltemp + + associate(pl_discards => self%pl_discards, nsppl => self%pl_discards%nbody, pl => self%pl, npl => self%pl%nbody) + if (self%tp_discards%nbody > 0) call io_write_discard(self, param) + + if (nsppl == 0) return + select case(param%out_stat) + case('APPEND') + open(unit = LUN, file = param%discard_out, status = 'OLD', position = 'APPEND', form = 'FORMATTED', iostat = ierr) + case('NEW', 'REPLACE', 'UNKNOWN') + open(unit = LUN, file = param%discard_out, status = param%out_stat, form = 'FORMATTED', iostat = ierr) + case default + write(*,*) 'Invalid status code for OUT_STAT: ',trim(adjustl(param%out_stat)) + call util_exit(FAILURE) + end select + lfirst = .false. + if (param%lgr) call pl_discards%pv2v(param) + + ! write(LUN, HDRFMT) param%t, nsp, param%lbig_discard + ! do i = 1, nsp + ! write(LUN, NAMEFMT) sub, tp_discards%id(i), tp_discards%status(i) + ! write(LUN, VECFMT) tp_discards%xh(1, i), tp_discards%xh(2, i), tp_discards%xh(3, i) + ! write(LUN, VECFMT) tp_discards%vh(1, i), tp_discards%vh(2, i), tp_discards%vh(3, i) + ! end do + ! if (param%lbig_discard) then + ! if (param%lgr) then + ! allocate(pltemp, source = pl) + ! call pltemp%pv2v(param) + ! allocate(vh, source = pltemp%vh) + ! deallocate(pltemp) + ! else + ! allocate(vh, source = pl%vh) + ! end if + + ! write(LUN, NPLFMT) npl + ! do i = 1, npl + ! write(LUN, PLNAMEFMT) pl%id(i), pl%Gmass(i), pl%radius(i) + ! write(LUN, VECFMT) pl%xh(1, i), pl%xh(2, i), pl%xh(3, i) + ! write(LUN, VECFMT) vh(1, i), vh(2, i), vh(3, i) + ! end do + ! deallocate(vh) + ! end if + ! close(LUN) + end associate + + return + end subroutine symba_io_write_discard + module subroutine symba_io_write_frame_info(self, iu, param) implicit none @@ -216,6 +279,5 @@ module subroutine symba_io_write_frame_info(self, iu, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters end subroutine symba_io_write_frame_info - end submodule s_symba_io From ad8520d83aad1aadad01e0110fe959badef176ff Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 17:58:37 -0400 Subject: [PATCH 22/42] Made somewhat functional SyMBA version of the discard method for pl --- src/io/io.f90 | 2 +- src/modules/symba_classes.f90 | 1 - src/setup/setup.f90 | 1 - src/symba/symba_collision.f90 | 6 +++--- src/symba/symba_drift.f90 | 8 ++++---- src/symba/symba_io.f90 | 27 ++++++++++++++++----------- src/symba/symba_kick.f90 | 6 +++--- src/util/util_append.f90 | 2 +- src/util/util_coord.f90 | 4 ++-- src/util/util_resize.f90 | 2 +- 10 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/io/io.f90 b/src/io/io.f90 index e3556b11c..2900fc7f4 100644 --- a/src/io/io.f90 +++ b/src/io/io.f90 @@ -1074,7 +1074,7 @@ module subroutine io_write_discard(self, param) write(LUN, HDRFMT) param%t, nsp, param%lbig_discard do i = 1, nsp - write(LUN, NAMEFMT) sub, tp_discards%id(i), tp_discards%status(i) + write(LUN, NAMEFMT) SUB, tp_discards%id(i), tp_discards%status(i) write(LUN, VECFMT) tp_discards%xh(1, i), tp_discards%xh(2, i), tp_discards%xh(3, i) write(LUN, VECFMT) tp_discards%vh(1, i), tp_discards%vh(2, i), tp_discards%vh(3, i) end do diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 2094b533a..c4b399471 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -164,7 +164,6 @@ module symba_classes class(symba_pl), allocatable :: mergesub_list !! List of subtracted bodies in mergers or collisions class(symba_pltpenc), allocatable :: pltpenc_list !! List of massive body-test particle encounters in a single step class(symba_plplenc), allocatable :: plplenc_list !! List of massive body-massive body encounters in a single step - class(symba_pl), allocatable :: pl_discards !! Discarded test particle data structure integer(I4B) :: irec !! System recursion level contains procedure :: write_discard => symba_io_write_discard !! Write out information about discarded and merged planets and test particles in SyMBA diff --git a/src/setup/setup.f90 b/src/setup/setup.f90 index f1e44f19c..7de8ce5c3 100644 --- a/src/setup/setup.f90 +++ b/src/setup/setup.f90 @@ -53,7 +53,6 @@ module subroutine setup_construct_system(system, param) allocate(symba_cb :: system%cb) allocate(symba_pl :: system%pl) allocate(symba_tp :: system%tp) - allocate(symba_pl :: system%pl_discards) allocate(symba_tp :: system%tp_discards) allocate(symba_pl :: system%mergeadd_list) allocate(symba_pl :: system%mergesub_list) diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 7c0a05c91..ed2e1e0a1 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -67,11 +67,11 @@ module subroutine symba_collision_check_plplenc(self, system, param, t, dt, irec lmask(:) = .false. lmask(ind1(k)) = .not.pl%lcollision(ind1(k)) lmask(ind2(k)) = .not.pl%lcollision(ind2(k)) - call system%mergesub_list%append(pl, lmask) - ! Set the collision flag for these to bodies to true in case they become involved in another collision later in the step pl%lcollision([ind1(k), ind2(k)]) = .true. - pl%ldiscard([ind1(k), ind2(k)]) = .true. + pl%lcollision([ind1(k), ind2(k)]) = .true. + pl%status([ind1(k), ind2(k)]) = COLLISION + call system%mergesub_list%append(pl, lmask) end do end if diff --git a/src/symba/symba_drift.f90 b/src/symba/symba_drift.f90 index ac06cbb6a..c4efee05f 100644 --- a/src/symba/symba_drift.f90 +++ b/src/symba/symba_drift.f90 @@ -17,9 +17,9 @@ module subroutine symba_drift_pl(self, system, param, dt) select type(system) class is (symba_nbody_system) - self%lmask(:) = self%status(:) == ACTIVE .and. self%levelg(:) == system%irec + self%lmask(:) = self%status(:) /= INACTIVE .and. self%levelg(:) == system%irec call helio_drift_body(self, system, param, dt) - self%lmask(:) = self%status(:) == ACTIVE + self%lmask(:) = self%status(:) /= INACTIVE end select return @@ -41,9 +41,9 @@ module subroutine symba_drift_tp(self, system, param, dt) select type(system) class is (symba_nbody_system) - self%lmask(:) = self%status(:) == ACTIVE .and. self%levelg(:) == system%irec + self%lmask(:) = self%status(:) /= INACTIVE .and. self%levelg(:) == system%irec call helio_drift_body(self, system, param, dt) - self%lmask(:) = self%status(:) == ACTIVE + self%lmask(:) = self%status(:) /= INACTIVE end select return diff --git a/src/symba/symba_io.f90 b/src/symba/symba_io.f90 index 97e4ab3f6..f35e45408 100644 --- a/src/symba/symba_io.f90 +++ b/src/symba/symba_io.f90 @@ -225,10 +225,10 @@ module subroutine symba_io_write_discard(self, param) character(*), parameter :: PLNAMEFMT = '(I8, 2(1X, E23.16))' class(swiftest_body), allocatable :: pltemp - associate(pl_discards => self%pl_discards, nsppl => self%pl_discards%nbody, pl => self%pl, npl => self%pl%nbody) + associate(pl => self%pl, npl => self%pl%nbody, mergesub_list => self%mergesub_list, mergeadd_list => self%mergeadd_list) if (self%tp_discards%nbody > 0) call io_write_discard(self, param) - if (nsppl == 0) return + if (mergesub_list%nbody == 0) return select case(param%out_stat) case('APPEND') open(unit = LUN, file = param%discard_out, status = 'OLD', position = 'APPEND', form = 'FORMATTED', iostat = ierr) @@ -239,14 +239,19 @@ module subroutine symba_io_write_discard(self, param) call util_exit(FAILURE) end select lfirst = .false. - if (param%lgr) call pl_discards%pv2v(param) - - ! write(LUN, HDRFMT) param%t, nsp, param%lbig_discard - ! do i = 1, nsp - ! write(LUN, NAMEFMT) sub, tp_discards%id(i), tp_discards%status(i) - ! write(LUN, VECFMT) tp_discards%xh(1, i), tp_discards%xh(2, i), tp_discards%xh(3, i) - ! write(LUN, VECFMT) tp_discards%vh(1, i), tp_discards%vh(2, i), tp_discards%vh(3, i) - ! end do + if (param%lgr) then + call mergesub_list%pv2v(param) + call mergeadd_list%pv2v(param) + end if + + write(LUN, HDRFMT) param%t, mergesub_list%nbody, param%lbig_discard + do i = 1, mergesub_list%nbody + write(LUN, NAMEFMT) SUB, mergesub_list%id(i), mergesub_list%status(i) + write(LUN, VECFMT) mergesub_list%xh(1, i), mergesub_list%xh(2, i), mergesub_list%xh(3, i) + write(LUN, VECFMT) mergesub_list%vh(1, i), mergesub_list%vh(2, i), mergesub_list%vh(3, i) + end do + + ! This is incomplete until the mergeadd_list methods are completed ! if (param%lbig_discard) then ! if (param%lgr) then ! allocate(pltemp, source = pl) @@ -265,7 +270,7 @@ module subroutine symba_io_write_discard(self, param) ! end do ! deallocate(vh) ! end if - ! close(LUN) + close(LUN) end associate return diff --git a/src/symba/symba_kick.f90 b/src/symba/symba_kick.f90 index aebb6bb2b..8625b3d81 100644 --- a/src/symba/symba_kick.f90 +++ b/src/symba/symba_kick.f90 @@ -124,8 +124,8 @@ module subroutine symba_kick_pltpenc(self, system, dt, irec, sgn) select type(tp => system%tp) class is (symba_tp) associate(ind1 => self%index1, ind2 => self%index2) - if (pl%nbody > 0) pl%lmask(:) = pl%status(:) == ACTIVE - if (tp%nbody > 0) tp%lmask(:) = tp%status(:) == ACTIVE + if (pl%nbody > 0) pl%lmask(:) = pl%status(:) /= INACTIVE + if (tp%nbody > 0) tp%lmask(:) = tp%status(:) /= INACTIVE irm1 = irec - 1 if (sgn < 0) then @@ -145,7 +145,7 @@ module subroutine symba_kick_pltpenc(self, system, dt, irec, sgn) else lgoodlevel = (pl%levelg(ind1(k)) >= irm1) .and. (tp%levelg(ind2(k)) >= irm1) end if - if ((self%status(k) == ACTIVE) .and. lgoodlevel) then + if ((self%status(k) /= INACTIVE) .and. lgoodlevel) then if (isplpl) then ri = ((pl%rhill(ind1(k)) + pl%rhill(ind2(k)))**2) * (RHSCALE**2) * (RSHELL**(2*irecl)) rim1 = ri * (RSHELL**2) diff --git a/src/util/util_append.f90 b/src/util/util_append.f90 index a13103cfa..0f7ac0bde 100644 --- a/src/util/util_append.f90 +++ b/src/util/util_append.f90 @@ -232,7 +232,7 @@ module subroutine util_append_body(self, source, lsource_mask) call util_append(self%omega, source%omega, lsource_mask) call util_append(self%capm, source%capm, lsource_mask) - self%nbody = count(self%status(:) == ACTIVE) + self%nbody = count(self%status(:) /= INACTIVE) return end subroutine util_append_body diff --git a/src/util/util_coord.f90 b/src/util/util_coord.f90 index bdc772d21..938d04951 100644 --- a/src/util/util_coord.f90 +++ b/src/util/util_coord.f90 @@ -54,7 +54,7 @@ module subroutine util_coord_h2b_tp(self, cb) associate(ntp => self%nbody, xbcb => cb%xb, vbcb => cb%vb, status => self%status, & xb => self%xb, xh => self%xh, vb => self%vb, vh => self%vh) - where(status(1:ntp) == ACTIVE) + where(status(1:ntp) /= INACTIVE) xb(1, 1:ntp) = xh(1, 1:ntp) + xbcb(1) xb(2, 1:ntp) = xh(2, 1:ntp) + xbcb(2) xb(3, 1:ntp) = xh(3, 1:ntp) + xbcb(3) @@ -109,7 +109,7 @@ module subroutine util_coord_b2h_tp(self, cb) associate(ntp => self%nbody, xbcb => cb%xb, vbcb => cb%vb, xb => self%xb, xh => self%xh, & vb => self%vb, vh => self%vh, status => self%status) - where(status(1:ntp) == ACTIVE) + where(status(1:ntp) /= INACTIVE) xh(1, 1:ntp) = xb(1, 1:ntp) - xbcb(1) xh(2, 1:ntp) = xb(2, 1:ntp) - xbcb(2) xh(3, 1:ntp) = xb(3, 1:ntp) - xbcb(3) diff --git a/src/util/util_resize.f90 b/src/util/util_resize.f90 index 4a84a003b..9abd66189 100644 --- a/src/util/util_resize.f90 +++ b/src/util/util_resize.f90 @@ -201,7 +201,7 @@ module subroutine util_resize_body(self, nnew) call util_resize(self%capom, nnew) call util_resize(self%omega, nnew) call util_resize(self%capm, nnew) - self%nbody = count(self%status(1:nnew) == ACTIVE) + self%nbody = count(self%status(1:nnew) /= INACTIVE) return end subroutine util_resize_body From c1ca5fc2c8bc91ff5215a199f2882f16265978d3 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 18:35:34 -0400 Subject: [PATCH 23/42] Added the central body discard code from the Fragmentation branch --- src/discard/discard.f90 | 6 +-- src/main/swiftest_driver.f90 | 2 +- src/symba/symba_discard.f90 | 89 +++++++++++++++++++++++++++++++++++- src/util/util_set.f90 | 2 +- 4 files changed, 93 insertions(+), 6 deletions(-) diff --git a/src/discard/discard.f90 b/src/discard/discard.f90 index 0c84c9e88..5f87ee752 100644 --- a/src/discard/discard.f90 +++ b/src/discard/discard.f90 @@ -65,7 +65,7 @@ module subroutine discard_tp(self, system, param) if (ntp > 0) call tp%h2b(cb) end if if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. (param%rmaxu >= 0.0_DP)) then - if (ntp > 0) call discard_sun_tp(tp, system, param) + if (ntp > 0) call discard_cb_tp(tp, system, param) end if if (param%qmin >= 0.0_DP .and. ntp > 0) call discard_peri_tp(tp, system, param) if (param%lclose .and. ntp > 0) call discard_pl_tp(tp, system, param) @@ -76,7 +76,7 @@ module subroutine discard_tp(self, system, param) end subroutine discard_tp - subroutine discard_sun_tp(tp, system, param) + subroutine discard_cb_tp(tp, system, param) !! author: David A. Minton !! !! Check to see if test particles should be discarded based on their positions relative to the Sun @@ -126,7 +126,7 @@ subroutine discard_sun_tp(tp, system, param) end associate return - end subroutine discard_sun_tp + end subroutine discard_cb_tp subroutine discard_peri_tp(tp, system, param) diff --git a/src/main/swiftest_driver.f90 b/src/main/swiftest_driver.f90 index 805264c2c..55eb1bc89 100644 --- a/src/main/swiftest_driver.f90 +++ b/src/main/swiftest_driver.f90 @@ -67,7 +67,7 @@ program swiftest_driver t = t0 + iloop * dt - !> Evaluate any discards or mergers + !> Evaluate any discards or collisional outcomes call nbody_system%discard(param) !> If the loop counter is at the output cadence value, append the data file with a single frame diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 3f8ada6fe..9a90d7ea1 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -8,8 +8,95 @@ module subroutine symba_discard_pl(self, system, param) class(symba_pl), intent(inout) :: self !! SyMBA test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - + + ! First check for collisions with the central body + associate(pl => self, npl => self%nbody, cb => system%cb) + if (npl == 0) return + if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. & + (param%rmaxu >= 0.0_DP) .or. ((param%qmin >= 0.0_DP) .and. (param%qmin_coord == "BARY"))) then + call pl%h2b(cb) + end if + if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. (param%rmaxu >= 0.0_DP)) then + call symba_discard_cb_pl(pl, system, param) + end if + if (param%qmin >= 0.0_DP .and. npl > 0) call symba_discard_peri_pl(pl, system, param) + end associate + + select type(param) + class is (symba_parameters) + if (param%lfragmentation) then + + end if + + end select + return end subroutine symba_discard_pl + + subroutine symba_discard_cb_pl(pl, system, param) + !! author: David A. Minton + !! + !! Check to see if planets should be discarded based on their positions relative to the central body + !! + !! Adapted from David E. Kaufmann's Swifter routine: symba_discard_cb.f90 + !! Adapted from Hal Levison's Swift routine discard_massive5.f + implicit none + ! Arguments + class(symba_pl), intent(inout) :: pl !! SyMBA massive body object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + integer(I4B) :: i, j + real(DP) :: energy, vb2, rb2, rh2, rmin2, rmax2, rmaxu2 + + associate(npl => pl%nbody, cb => system%cb) + call system%set_msys() + rmin2 = param%rmin**2 + rmax2 = param%rmax*2 + rmaxu2 = param%rmaxu**2 + do i = 1, npl + if (pl%status(i) == ACTIVE) then + rh2 = dot_product(pl%xh(:,i), pl%xh(:,i)) + if ((param%rmax >= 0.0_DP) .and. (rh2 > rmax2)) then + pl%ldiscard(i) = .true. + pl%status(i) = DISCARDED_RMAX + write(*, *) "Massive body ", pl%id(i), " too far from the central body at t = ", param%t + else if ((param%rmin >= 0.0_DP) .and. (rh2 < rmin2)) then + pl%ldiscard(i) = .true. + pl%status(i) = DISCARDED_RMIN + write(*, *) "Massive body ", pl%id(i), " too close to the central body at t = ", param%t + else if (param%rmaxu >= 0.0_DP) then + rb2 = dot_product(pl%xb(:,i), pl%xb(:,i)) + vb2 = dot_product(pl%vb(:,i), pl%vb(:,i)) + energy = 0.5_DP * vb2 - system%msys / sqrt(rb2) + if ((energy > 0.0_DP) .and. (rb2 > rmaxu2)) then + pl%ldiscard(i) = .true. + pl%status(i) = DISCARDED_RMAXU + write(*, *) "Massive body ", pl%id(i), " is unbound and too far from barycenter at t = ", param%t + end if + end if + end if + end do + end associate + + return + end subroutine symba_discard_cb_pl + + + subroutine symba_discard_peri_pl(pl, system, param) + !! author: David A. Minton + !! + !! Check to see if a test particle should be discarded because its perihelion distance becomes too small + !! + !! Adapted from David E. Kaufmann's Swifter routine: discard_peri.f90 + !! Adapted from Hal Levison's Swift routine discard_peri.f + implicit none + ! Arguments + class(symba_pl), intent(inout) :: pl !! SyMBA massive body object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + return + end subroutine symba_discard_peri_pl + end submodule s_symba_discard \ No newline at end of file diff --git a/src/util/util_set.f90 b/src/util/util_set.f90 index c401cb0ce..a1c4075b6 100644 --- a/src/util/util_set.f90 +++ b/src/util/util_set.f90 @@ -62,7 +62,7 @@ module subroutine util_set_msys(self) ! Arguments class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nobdy system object - self%msys = self%cb%mass + sum(self%pl%mass(1:self%pl%nbody)) + self%msys = self%cb%Gmass + sum(self%pl%Gmass(1:self%pl%nbody), self%pl%status(1:self%pl%nbody) /= INACTIVE) return end subroutine util_set_msys From aa3e810729bdd5d69cb40c7a7529eaf86c32aa86 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 19:08:49 -0400 Subject: [PATCH 24/42] Removed the mergesub_list call from inside the symba step --- src/symba/symba_collision.f90 | 5 ----- src/symba/symba_discard.f90 | 8 +++++++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index ed2e1e0a1..2614a486a 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -63,15 +63,10 @@ module subroutine symba_collision_check_plplenc(self, system, param, t, dt, irec ! Check to see if either of these bodies has been involved with a collision before, and if so, make this a collisional family if (pl%lcollision(ind1(k)) .or. pl%lcollision(ind2(k))) call pl%make_family([ind1(k),ind2(k)]) - ! Add any of the bodies that have *not* previously been involved in a collision to the subtraction list - lmask(:) = .false. - lmask(ind1(k)) = .not.pl%lcollision(ind1(k)) - lmask(ind2(k)) = .not.pl%lcollision(ind2(k)) ! Set the collision flag for these to bodies to true in case they become involved in another collision later in the step pl%lcollision([ind1(k), ind2(k)]) = .true. pl%lcollision([ind1(k), ind2(k)]) = .true. pl%status([ind1(k), ind2(k)]) = COLLISION - call system%mergesub_list%append(pl, lmask) end do end if diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 9a90d7ea1..f9066fdc6 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -37,7 +37,10 @@ end subroutine symba_discard_pl subroutine symba_discard_cb_pl(pl, system, param) !! author: David A. Minton !! - !! Check to see if planets should be discarded based on their positions relative to the central body + !! Check to see if planets should be discarded based on their positions relative to the central body. + !! If a body gets flagged here when it has also been previously flagged for a collision with another massive body, + !! its collisional status will be revoked. Discards due to colliding with or escaping the central body take precedence + !! over pl-pl collisions !! !! Adapted from David E. Kaufmann's Swifter routine: symba_discard_cb.f90 !! Adapted from Hal Levison's Swift routine discard_massive5.f @@ -60,10 +63,12 @@ subroutine symba_discard_cb_pl(pl, system, param) rh2 = dot_product(pl%xh(:,i), pl%xh(:,i)) if ((param%rmax >= 0.0_DP) .and. (rh2 > rmax2)) then pl%ldiscard(i) = .true. + pl%lcollision(i) = .false. pl%status(i) = DISCARDED_RMAX write(*, *) "Massive body ", pl%id(i), " too far from the central body at t = ", param%t else if ((param%rmin >= 0.0_DP) .and. (rh2 < rmin2)) then pl%ldiscard(i) = .true. + pl%lcollision(i) = .false. pl%status(i) = DISCARDED_RMIN write(*, *) "Massive body ", pl%id(i), " too close to the central body at t = ", param%t else if (param%rmaxu >= 0.0_DP) then @@ -72,6 +77,7 @@ subroutine symba_discard_cb_pl(pl, system, param) energy = 0.5_DP * vb2 - system%msys / sqrt(rb2) if ((energy > 0.0_DP) .and. (rb2 > rmaxu2)) then pl%ldiscard(i) = .true. + pl%lcollision(i) = .false. pl%status(i) = DISCARDED_RMAXU write(*, *) "Massive body ", pl%id(i), " is unbound and too far from barycenter at t = ", param%t end if From 947c4d47f1fcab1f5a8fb57002491941198d0fb8 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 20:26:30 -0400 Subject: [PATCH 25/42] Moved encounter type up to swiftest_classes so that the fragmentation code can be written independently of SyMBA --- src/modules/swiftest_classes.f90 | 18 +++++++++++++++++- src/modules/symba_classes.f90 | 19 ++++++++----------- src/symba/symba_util.f90 | 19 +++++++++---------- src/util/util_copy.f90 | 25 +++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 22 deletions(-) create mode 100644 src/util/util_copy.f90 diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 83514a2ab..b55dfb5e2 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -75,7 +75,7 @@ module swiftest_classes logical :: lintegrate = .false. !! Flag indicating that this object should be integrated in the current step contains !! The minimal methods that all systems must have - procedure :: dump => io_dump_swiftest + procedure :: dump => io_dump_swiftest procedure(abstract_initialize), deferred :: initialize procedure(abstract_read_frame), deferred :: read_frame procedure(abstract_write_frame), deferred :: write_frame @@ -286,6 +286,16 @@ module swiftest_classes procedure :: set_msys => util_set_msys !! Sets the value of msys from the masses of system bodies. end type swiftest_nbody_system + type :: swiftest_encounter + integer(I4B) :: nenc !! Total number of encounters + logical, dimension(:), allocatable :: lvdotr !! relative vdotr flag + integer(I4B), dimension(:), allocatable :: status !! status of the interaction + integer(I4B), dimension(:), allocatable :: index1 !! position of the first body in the encounter + integer(I4B), dimension(:), allocatable :: index2 !! position of the second body in the encounter + contains + procedure :: copy => util_copy_encounter + end type swiftest_encounter + abstract interface subroutine abstract_discard_body(self, system, param) import swiftest_body, swiftest_nbody_system, swiftest_parameters @@ -824,6 +834,12 @@ module subroutine util_coord_h2b_tp(self, cb) class(swiftest_cb), intent(in) :: cb !! Swiftest central body object end subroutine util_coord_h2b_tp + module subroutine util_copy_encounter(self, source) + implicit none + class(swiftest_encounter), intent(inout) :: self !! Encounter list + class(swiftest_encounter), intent(in) :: source !! Source object to copy into + end subroutine util_copy_encounter + module subroutine util_exit(code) implicit none integer(I4B), intent(in) :: code !! Failure exit code diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index c4b399471..a8c6ff716 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -4,7 +4,7 @@ module symba_classes !! Definition of classes and methods specific to the Democratic SyMBAcentric Method !! Adapted from David E. Kaufmann's Swifter routine: helio.f90 use swiftest_globals - use swiftest_classes, only : swiftest_parameters, swiftest_base + use swiftest_classes, only : swiftest_parameters, swiftest_base, swiftest_encounter use helio_classes, only : helio_cb, helio_pl, helio_tp, helio_nbody_system use rmvs_classes, only : rmvs_chk_ind implicit none @@ -125,13 +125,8 @@ module symba_classes ! symba_pltpenc class definitions and method interfaces !******************************************************************************************************************************* !> SyMBA class for tracking pl-tp close encounters in a step - type :: symba_pltpenc - integer(I4B) :: nenc !! Total number of encounters - logical, dimension(:), allocatable :: lvdotr !! relative vdotr flag - integer(I4B), dimension(:), allocatable :: status !! status of the interaction + type, extends(swiftest_encounter) :: symba_pltpenc integer(I4B), dimension(:), allocatable :: level !! encounter recursion level - integer(I4B), dimension(:), allocatable :: index1 !! position of the planet in encounter - integer(I4B), dimension(:), allocatable :: index2 !! position of the test particle in encounter contains procedure :: collision_check => symba_collision_check_pltpenc !! Checks if a test particle is going to collide with a massive body procedure :: encounter_check => symba_encounter_check_pltpenc !! Checks if massive bodies are going through close encounters with each other @@ -465,15 +460,17 @@ module subroutine symba_util_append_tp(self, source, lsource_mask) end subroutine symba_util_append_tp module subroutine symba_util_copy_pltpenc(self, source) + use swiftest_classes, only : swiftest_encounter implicit none - class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - class(symba_pltpenc), intent(in) :: source !! Source object to copy into + class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list + class(swiftest_encounter), intent(in) :: source !! Source object to copy into end subroutine symba_util_copy_pltpenc module subroutine symba_util_copy_plplenc(self, source) + use swiftest_classes, only : swifest_encounter implicit none - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list - class(symba_pltpenc), intent(in) :: source !! Source object to copy into + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(swiftest_encounter), intent(in) :: source !! Source object to copy into end subroutine symba_util_copy_plplenc end interface diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index bdfbea86c..e76c2faff 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -148,16 +148,15 @@ module subroutine symba_util_copy_pltpenc(self, source) !! Copies elements from the source encounter list into self. implicit none ! Arguments - class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - class(symba_pltpenc), intent(in) :: source !! Source object to copy into + class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list + class(swiftest_encounter), intent(in) :: source !! Source object to copy into + call util_copy_encounter(self, source) associate(n => source%nenc) - self%nenc = n - self%lvdotr(1:n) = source%lvdotr(1:n) - self%status(1:n) = source%status(1:n) - self%level(1:n) = source%level(1:n) - self%index1(1:n) = source%index1(1:n) - self%index2(1:n) = source%index2(1:n) + select type(source) + class is (symba_pltpenc) + self%level(1:n) = source%level(1:n) + end select end associate return @@ -170,8 +169,8 @@ module subroutine symba_util_copy_plplenc(self, source) !! Copies elements from the source encounter list into self. implicit none ! Arguments - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list - class(symba_pltpenc), intent(in) :: source !! Source object to copy into + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(swiftest_encounter), intent(in) :: source !! Source object to copy into call symba_util_copy_pltpenc(self, source) associate(n => source%nenc) diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 new file mode 100644 index 000000000..704e10d64 --- /dev/null +++ b/src/util/util_copy.f90 @@ -0,0 +1,25 @@ +submodule(swiftest_classes) s_util_copy + use swiftest +contains + +module subroutine util_copy_encounter(self, source) + !! author: David A. Minton + !! + !! Copies elements from the source encounter list into self. + implicit none + ! Arguments + class(swiftest_encounter), intent(inout) :: self !! Encounter list + class(swiftest_encounter), intent(in) :: source !! Source object to copy into + + associate(n => source%nenc) + self%nenc = n + self%lvdotr(1:n) = source%lvdotr(1:n) + self%status(1:n) = source%status(1:n) + self%index1(1:n) = source%index1(1:n) + self%index2(1:n) = source%index2(1:n) + end associate + + return +end subroutine util_copy_encounter + +end submodule s_util_copy From 9efb88ca97498fdcbfce70e38668ac798b2bafc4 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Mon, 2 Aug 2021 23:48:25 -0400 Subject: [PATCH 26/42] Consolidated pltp/plpl encounter lists into a single encounter object --- src/modules/swiftest_classes.f90 | 20 +++- src/modules/symba_classes.f90 | 33 ------- src/setup/setup.f90 | 44 +++++++++ src/symba/symba_collision.f90 | 154 +++++++++++-------------------- src/symba/symba_setup.f90 | 47 +--------- src/symba/symba_util.f90 | 62 ------------- src/util/util_copy.f90 | 4 + src/util/util_resize.f90 | 35 +++++++ 8 files changed, 159 insertions(+), 240 deletions(-) diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index b55dfb5e2..fdb2360ee 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -292,8 +292,14 @@ module swiftest_classes integer(I4B), dimension(:), allocatable :: status !! status of the interaction integer(I4B), dimension(:), allocatable :: index1 !! position of the first body in the encounter integer(I4B), dimension(:), allocatable :: index2 !! position of the second body in the encounter + real(DP), dimension(:,:), allocatable :: x1 !! the position of body 1 in the encounter + real(DP), dimension(:,:), allocatable :: x2 !! the position of body 2 in the encounter + real(DP), dimension(:,:), allocatable :: v1 !! the velocity of body 1 in the encounter + real(DP), dimension(:,:), allocatable :: v2 !! the velocity of body 2 in the encounter contains - procedure :: copy => util_copy_encounter + procedure :: copy => util_copy_encounter + procedure :: resize => util_resize_encounter + procedure :: setup => setup_encounter end type swiftest_encounter abstract interface @@ -707,6 +713,12 @@ module subroutine setup_construct_system(system, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters end subroutine setup_construct_system + module subroutine setup_encounter(self, n) + implicit none + class(swiftest_encounter), intent(inout) :: self !! Swiftest encounter structure + integer(I4B), intent(in) :: n !! Number of encounters to allocate space for + end subroutine setup_encounter + module subroutine setup_initialize_system(self, param) implicit none class(swiftest_nbody_system), intent(inout) :: self !! Swiftest system object @@ -952,6 +964,12 @@ module subroutine util_resize_body(self, nnew) integer(I4B), intent(in) :: nnew !! New size neded end subroutine util_resize_body + module subroutine util_resize_encounter(self, nnew) + implicit none + class(swiftest_encounter), intent(inout) :: self !! Swiftest encounter list + integer(I4B), intent(in) :: nnew !! New size of list needed + end subroutine util_resize_encounter + module subroutine util_resize_pl(self, nnew) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index a8c6ff716..92caa0bb3 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -133,7 +133,6 @@ module symba_classes procedure :: kick => symba_kick_pltpenc !! Kick barycentric velocities of active test particles within SyMBA recursion procedure :: setup => symba_setup_pltpenc !! A constructor that sets the number of encounters and allocates and initializes all arrays procedure :: copy => symba_util_copy_pltpenc !! Copies all elements of one pltpenc list to another - procedure :: resize => symba_util_resize_pltpenc !! Checks the current size of the pltpenc_list against the required size and extends it by a factor of 2 more than requested if it is too small end type symba_pltpenc !******************************************************************************************************************************** @@ -141,14 +140,7 @@ module symba_classes !******************************************************************************************************************************* !> SyMBA class for tracking pl-pl close encounters in a step type, extends(symba_pltpenc) :: symba_plplenc - real(DP), dimension(:,:), allocatable :: xh1 !! the heliocentric position of parent 1 in encounter - real(DP), dimension(:,:), allocatable :: xh2 !! the heliocentric position of parent 2 in encounter - real(DP), dimension(:,:), allocatable :: vb1 !! the barycentric velocity of parent 1 in encounter - real(DP), dimension(:,:), allocatable :: vb2 !! the barycentric velocity of parent 2 in encounter contains - procedure :: collision_check => symba_collision_check_plplenc !! Checks if two massive bodies are going to collide - procedure :: setup => symba_setup_plplenc !! A constructor that sets the number of encounters and allocates and initializes all arrays - procedure :: copy => symba_util_copy_plplenc !! Copies all elements of one plplenc list to another end type symba_plplenc !******************************************************************************************************************************** @@ -182,17 +174,6 @@ module subroutine symba_collision_check_pltpenc(self, system, param, t, dt, irec integer(I4B), intent(in) :: irec !! Current recursion level end subroutine symba_collision_check_pltpenc - module subroutine symba_collision_check_plplenc(self, system, param, t, dt, irec) - use swiftest_classes, only : swiftest_parameters - implicit none - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-tp encounter list object - class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! current time - real(DP), intent(in) :: dt !! step size - integer(I4B), intent(in) :: irec !! Current recursion level - end subroutine symba_collision_check_plplenc - module subroutine symba_collision_make_family_pl(self,idx) implicit none class(symba_pl), intent(inout) :: self !! SyMBA massive body object @@ -343,7 +324,6 @@ module subroutine symba_kick_pltpenc(self, system, dt, irec, sgn) integer(I4B), intent(in) :: sgn !! sign to be applied to acceleration end subroutine symba_kick_pltpenc - module subroutine symba_io_write_frame_info(self, iu, param) use swiftest_classes, only : swiftest_parameters implicit none @@ -465,13 +445,6 @@ module subroutine symba_util_copy_pltpenc(self, source) class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list class(swiftest_encounter), intent(in) :: source !! Source object to copy into end subroutine symba_util_copy_pltpenc - - module subroutine symba_util_copy_plplenc(self, source) - use swiftest_classes, only : swifest_encounter - implicit none - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list - class(swiftest_encounter), intent(in) :: source !! Source object to copy into - end subroutine symba_util_copy_plplenc end interface interface util_fill @@ -529,12 +502,6 @@ module subroutine symba_util_resize_pl(self, nnew) integer(I4B), intent(in) :: nnew !! New size neded end subroutine symba_util_resize_pl - module subroutine symba_util_resize_pltpenc(self, nnew) - implicit none - class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - integer(I4B), intent(in) :: nnew !! New size of list needed - end subroutine symba_util_resize_pltpenc - module subroutine symba_util_resize_tp(self, nnew) implicit none class(symba_tp), intent(inout) :: self !! SyMBA massive body object diff --git a/src/setup/setup.f90 b/src/setup/setup.f90 index 7de8ce5c3..ca5f38c6e 100644 --- a/src/setup/setup.f90 +++ b/src/setup/setup.f90 @@ -70,6 +70,50 @@ module subroutine setup_construct_system(system, param) end subroutine setup_construct_system + module subroutine setup_encounter(self, n) + !! author: David A. Minton + !! + !! A constructor that sets the number of encounters and allocates and initializes all arrays + !! + implicit none + ! Arguments + class(swiftest_encounter), intent(inout) :: self !! Swiftest encounter structure + integer(I4B), intent(in) :: n !! Number of encounters to allocate space for + + self%nenc = n + if (n == 0) return + + if (allocated(self%lvdotr)) deallocate(self%lvdotr) + if (allocated(self%status)) deallocate(self%status) + if (allocated(self%index1)) deallocate(self%index1) + if (allocated(self%index2)) deallocate(self%index2) + if (allocated(self%x1)) deallocate(self%x1) + if (allocated(self%x2)) deallocate(self%x2) + if (allocated(self%v1)) deallocate(self%v1) + if (allocated(self%v2)) deallocate(self%v2) + + allocate(self%lvdotr(n)) + allocate(self%status(n)) + allocate(self%index1(n)) + allocate(self%index2(n)) + allocate(self%x1(NDIM,n)) + allocate(self%x2(NDIM,n)) + allocate(self%v1(NDIM,n)) + allocate(self%v2(NDIM,n)) + + self%lvdotr(:) = .false. + self%status(:) = INACTIVE + self%index1(:) = 0 + self%index2(:) = 0 + self%x1(:,:) = 0.0_DP + self%x2(:,:) = 0.0_DP + self%v1(:,:) = 0.0_DP + self%v2(:,:) = 0.0_DP + + return + end subroutine setup_encounter + + module subroutine setup_initialize_system(self, param) !! author: David A. Minton !! diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 2614a486a..bb67508fd 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -2,89 +2,12 @@ use swiftest contains - module subroutine symba_collision_check_plplenc(self, system, param, t, dt, irec) - !! author: Jennifer L.L. Pouplin, Carlisle A. wishard, and David A. Minton - !! - !! Check for merger between massive bodies in SyMBA. If the user has turned on the FRAGMENTATION feature, it will call the - !! symba_regime subroutine to determine what kind of collision will occur. - !! - !! Adapted from David E. Kaufmann's Swifter routine symba_merge_pl.f90 - !! - !! Adapted from Hal Levison's Swift routine symba5_merge.f - implicit none - ! Arguments - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-tp encounter list object - class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - real(DP), intent(in) :: t !! current time - real(DP), intent(in) :: dt !! step size - integer(I4B), intent(in) :: irec !! Current recursion level - ! Internals - logical, dimension(:), allocatable :: lcollision, lmask - real(DP), dimension(NDIM) :: xr, vr - integer(I4B) :: k - real(DP) :: rlim, mtot - - if (self%nenc == 0) return - - select type(pl => system%pl) - class is (symba_pl) - associate(plplenc_list => self, nplplenc => self%nenc, ind1 => self%index1, ind2 => self%index2) - allocate(lmask(nplplenc)) - lmask(:) = ((plplenc_list%status(1:nplplenc) == ACTIVE) & - .and. (pl%levelg(ind1(1:nplplenc)) >= irec) & - .and. (pl%levelg(ind2(1:nplplenc)) >= irec)) - if (.not.any(lmask(:))) return - - allocate(lcollision(nplplenc)) - lcollision(:) = .false. - - do concurrent(k = 1:nplplenc, lmask(k)) - xr(:) = pl%xh(:, ind1(k)) - pl%xh(:, ind2(k)) - vr(:) = pl%vb(:, ind1(k)) - pl%vb(:, ind2(k)) - rlim = pl%radius(ind1(k)) + pl%radius(ind2(k)) - mtot = pl%Gmass(ind1(k)) + pl%Gmass(ind2(k)) - lcollision(k) = symba_collision_check_one(xr(1), xr(2), xr(3), vr(1), vr(2), vr(3), mtot, rlim, dt, plplenc_list%lvdotr(k)) - end do - deallocate(lmask) - - if (any(lcollision(:))) then - allocate(lmask(pl%nbody)) - do k = 1, nplplenc - if (.not.lcollision(k)) cycle - - ! Set this encounter as a collision and save the position and velocity vectors at the time of the collision - plplenc_list%status(k) = COLLISION - plplenc_list%xh1(:,k) = pl%xh(:,ind1(k)) - plplenc_list%vb1(:,k) = pl%vb(:,ind1(k)) - plplenc_list%xh2(:,k) = pl%xh(:,ind2(k)) - plplenc_list%vb2(:,k) = pl%vb(:,ind2(k)) - - ! Check to see if either of these bodies has been involved with a collision before, and if so, make this a collisional family - if (pl%lcollision(ind1(k)) .or. pl%lcollision(ind2(k))) call pl%make_family([ind1(k),ind2(k)]) - - ! Set the collision flag for these to bodies to true in case they become involved in another collision later in the step - pl%lcollision([ind1(k), ind2(k)]) = .true. - pl%lcollision([ind1(k), ind2(k)]) = .true. - pl%status([ind1(k), ind2(k)]) = COLLISION - end do - - end if - end associate - end select - - return - - return - end subroutine symba_collision_check_plplenc - - module subroutine symba_collision_check_pltpenc(self, system, param, t, dt, irec) !! author: David A. Minton !! !! Check for merger between massive bodies and test particles in SyMBA !! - !! Adapted from David E. Kaufmann's Swifter routine symba_merge_tp.f90 + !! Adapted from David E. Kaufmann's Swifter routine symba_merge.f90 and symba_merge_tp.f90 !! !! Adapted from Hal Levison's Swift routine symba5_merge.f implicit none @@ -99,39 +22,74 @@ module subroutine symba_collision_check_pltpenc(self, system, param, t, dt, irec logical, dimension(:), allocatable :: lcollision, lmask real(DP), dimension(NDIM) :: xr, vr integer(I4B) :: k + real(DP) :: rlim, mtot + logical :: isplpl if (self%nenc == 0) return + select type(self) + class is (symba_plplenc) + isplpl = .true. + class default + isplpl = .false. + end select select type(pl => system%pl) class is (symba_pl) select type(tp => system%tp) class is (symba_tp) - associate(pltpenc_list => self, npltpenc => self%nenc, plind => self%index1, tpind => self%index2) - allocate(lmask(npltpenc)) - lmask(:) = ((pltpenc_list%status(1:npltpenc) == ACTIVE) & - .and. (pl%levelg(plind(1:npltpenc)) >= irec) & - .and. (tp%levelg(tpind(1:npltpenc)) >= irec)) + associate(nenc => self%nenc, ind1 => self%index1, ind2 => self%index2) + allocate(lmask(nenc)) + lmask(:) = ((self%status(1:nenc) == ACTIVE) .and. (pl%levelg(ind1(1:nenc)) >= irec)) + if (isplpl) then + lmask(:) = lmask(:) .and. (pl%levelg(ind2(1:nenc)) >= irec) + else + lmask(:) = lmask(:) .and. (tp%levelg(ind2(1:nenc)) >= irec) + end if if (.not.any(lmask(:))) return - allocate(lcollision(npltpenc)) + allocate(lcollision(nenc)) lcollision(:) = .false. - do concurrent(k = 1:npltpenc, lmask(k)) - xr(:) = pl%xh(:, plind(k)) - tp%xh(:, tpind(k)) - vr(:) = pl%vb(:, plind(k)) - tp%vb(:, tpind(k)) - lcollision(k) = symba_collision_check_one(xr(1), xr(2), xr(3), vr(1), vr(2), vr(3), pl%Gmass(plind(k)), pl%radius(plind(k)), dt, pltpenc_list%lvdotr(k)) - end do + if (isplpl) then + do concurrent(k = 1:nenc, lmask(k)) + xr(:) = pl%xh(:, ind1(k)) - pl%xh(:, ind2(k)) + vr(:) = pl%vb(:, ind1(k)) - pl%vb(:, ind2(k)) + rlim = pl%radius(ind1(k)) + pl%radius(ind2(k)) + mtot = pl%Gmass(ind1(k)) + pl%Gmass(ind2(k)) + lcollision(k) = symba_collision_check_one(xr(1), xr(2), xr(3), vr(1), vr(2), vr(3), mtot, rlim, dt, self%lvdotr(k)) + end do + else + do concurrent(k = 1:nenc, lmask(k)) + xr(:) = pl%xh(:, ind1(k)) - tp%xh(:, ind2(k)) + vr(:) = pl%vb(:, ind1(k)) - tp%vb(:, ind2(k)) + lcollision(k) = symba_collision_check_one(xr(1), xr(2), xr(3), vr(1), vr(2), vr(3), pl%Gmass(ind1(k)), pl%radius(ind1(k)), dt, self%lvdotr(k)) + end do + end if if (any(lcollision(:))) then - where(lcollision(1:npltpenc)) - pltpenc_list%status(1:npltpenc) = COLLISION - tp%status(tpind(1:npltpenc)) = DISCARDED_PLR - tp%ldiscard(tpind(1:npltpenc)) = .true. - end where - - do k = 1, npltpenc - if (pltpenc_list%status(k) /= COLLISION) cycle - write(*,*) 'Test particle ',tp%id(tpind(k)), ' collided with massive body ',pl%id(plind(k)), ' at time ',t + do k = 1, nenc + if (.not.lcollision(k)) cycle + self%status(k) = COLLISION + self%x1(:,k) = pl%xh(:,ind1(k)) + self%v1(:,k) = pl%vb(:,ind1(k)) + if (isplpl) then + self%x2(:,k) = pl%xh(:,ind2(k)) + self%v2(:,k) = pl%vb(:,ind2(k)) + + ! Check to see if either of these bodies has been involved with a collision before, and if so, make this a collisional family + if (pl%lcollision(ind1(k)) .or. pl%lcollision(ind2(k))) call pl%make_family([ind1(k),ind2(k)]) + + ! Set the collision flag for these to bodies to true in case they become involved in another collision later in the step + pl%lcollision([ind1(k), ind2(k)]) = .true. + pl%ldiscard([ind1(k), ind2(k)]) = .true. + pl%status([ind1(k), ind2(k)]) = COLLISION + else + self%x2(:,k) = tp%xh(:,ind2(k)) + self%v2(:,k) = tp%vb(:,ind2(k)) + tp%status(ind2(k)) = DISCARDED_PLR + tp%ldiscard(ind2(k)) = .true. + write(*,*) 'Test particle ',tp%id(ind2(k)), ' collided with massive body ',pl%id(ind1(k)), ' at time ',t + end if end do end if end associate diff --git a/src/symba/symba_setup.f90 b/src/symba/symba_setup.f90 index f2c8e63dd..524420609 100644 --- a/src/symba/symba_setup.f90 +++ b/src/symba/symba_setup.f90 @@ -105,63 +105,18 @@ module subroutine symba_setup_pltpenc(self, n) class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter structure integer(I4B), intent(in) :: n !! Number of encounters to allocate space for - self%nenc = n + call setup_encounter(self, n) if (n == 0) return - if (allocated(self%lvdotr)) deallocate(self%lvdotr) - if (allocated(self%status)) deallocate(self%status) if (allocated(self%level)) deallocate(self%level) - if (allocated(self%index1)) deallocate(self%index1) - if (allocated(self%index2)) deallocate(self%index2) - - allocate(self%lvdotr(n)) - allocate(self%status(n)) allocate(self%level(n)) - allocate(self%index1(n)) - allocate(self%index2(n)) - self%lvdotr(:) = .false. - self%status(:) = INACTIVE self%level(:) = -1 - self%index1(:) = 0 - self%index2(:) = 0 return end subroutine symba_setup_pltpenc - module subroutine symba_setup_plplenc(self, n) - !! author: David A. Minton - !! - !! A constructor that sets the number of encounters and allocates and initializes all arrays - ! - implicit none - ! Arguments - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-tp encounter structure - integer(I4B), intent(in) :: n !! Number of encounters to allocate space for - - call symba_setup_pltpenc(self, n) - if (n == 0) return - - if (allocated(self%xh1)) deallocate(self%xh1) - if (allocated(self%xh2)) deallocate(self%xh2) - if (allocated(self%vb1)) deallocate(self%vb1) - if (allocated(self%vb2)) deallocate(self%vb2) - - allocate(self%xh1(NDIM,n)) - allocate(self%xh2(NDIM,n)) - allocate(self%vb1(NDIM,n)) - allocate(self%vb2(NDIM,n)) - - self%xh1(:,:) = 0.0_DP - self%xh2(:,:) = 0.0_DP - self%vb1(:,:) = 0.0_DP - self%vb2(:,:) = 0.0_DP - - return - end subroutine symba_setup_plplenc - - module subroutine symba_setup_tp(self, n, param) !! author: David A. Minton !! diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index e76c2faff..feda27a07 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -162,31 +162,6 @@ module subroutine symba_util_copy_pltpenc(self, source) return end subroutine symba_util_copy_pltpenc - - module subroutine symba_util_copy_plplenc(self, source) - !! author: David A. Minton - !! - !! Copies elements from the source encounter list into self. - implicit none - ! Arguments - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list - class(swiftest_encounter), intent(in) :: source !! Source object to copy into - - call symba_util_copy_pltpenc(self, source) - associate(n => source%nenc) - select type(source) - class is (symba_plplenc) - self%xh1(:,1:n) = source%xh1(:,1:n) - self%xh2(:,1:n) = source%xh2(:,1:n) - self%vb1(:,1:n) = source%vb1(:,1:n) - self%vb2(:,1:n) = source%vb2(:,1:n) - end select - end associate - - return - end subroutine symba_util_copy_plplenc - - module subroutine symba_util_fill_arr_info(keeps, inserts, lfill_list) !! author: David A. Minton !! @@ -410,43 +385,6 @@ module subroutine symba_util_resize_tp(self, nnew) return end subroutine symba_util_resize_tp - - module subroutine symba_util_resize_pltpenc(self, nnew) - !! author: David A. Minton - !! - !! Checks the current size of the encounter list against the required size and extends it by a factor of 2 more than requested if it is too small. - !! Polymorphic method works on both symba_pltpenc and symba_plplenc types - implicit none - ! Arguments - class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - integer(I4B), intent(in) :: nnew !! New size of list needed - ! Internals - class(symba_pltpenc), allocatable :: enc_temp - integer(I4B) :: nold - logical :: lmalloc - - lmalloc = allocated(self%status) - if (lmalloc) then - nold = size(self%status) - else - nold = 0 - end if - if (nnew > nold) then - if (lmalloc) allocate(enc_temp, source=self) - call self%setup(2 * nnew) - if (lmalloc) then - call self%copy(enc_temp) - deallocate(enc_temp) - end if - else - self%status(nnew+1:nold) = INACTIVE - end if - self%nenc = nnew - - return - end subroutine symba_util_resize_pltpenc - - module subroutine symba_util_sort_pl(self, sortby, ascending) !! author: David A. Minton !! diff --git a/src/util/util_copy.f90 b/src/util/util_copy.f90 index 704e10d64..f44777eec 100644 --- a/src/util/util_copy.f90 +++ b/src/util/util_copy.f90 @@ -17,6 +17,10 @@ module subroutine util_copy_encounter(self, source) self%status(1:n) = source%status(1:n) self%index1(1:n) = source%index1(1:n) self%index2(1:n) = source%index2(1:n) + self%x1(:,1:n) = source%x1(:,1:n) + self%x2(:,1:n) = source%x2(:,1:n) + self%v1(:,1:n) = source%v1(:,1:n) + self%v2(:,1:n) = source%v2(:,1:n) end associate return diff --git a/src/util/util_resize.f90 b/src/util/util_resize.f90 index 9abd66189..3772a8207 100644 --- a/src/util/util_resize.f90 +++ b/src/util/util_resize.f90 @@ -207,6 +207,41 @@ module subroutine util_resize_body(self, nnew) end subroutine util_resize_body + module subroutine util_resize_encounter(self, nnew) + !! author: David A. Minton + !! + !! Checks the current size of the encounter list against the required size and extends it by a factor of 2 more than requested if it is too small. + implicit none + ! Arguments + class(swiftest_encounter), intent(inout) :: self !! Swiftest encounter list + integer(I4B), intent(in) :: nnew !! New size of list needed + ! Internals + class(swiftest_encounter), allocatable :: enc_temp + integer(I4B) :: nold + logical :: lmalloc + + lmalloc = allocated(self%status) + if (lmalloc) then + nold = size(self%status) + else + nold = 0 + end if + if (nnew > nold) then + if (lmalloc) allocate(enc_temp, source=self) + call self%setup(2 * nnew) + if (lmalloc) then + call self%copy(enc_temp) + deallocate(enc_temp) + end if + else + self%status(nnew+1:nold) = INACTIVE + end if + self%nenc = nnew + + return + end subroutine util_resize_encounter + + module subroutine util_resize_pl(self, nnew) !! author: David A. Minton !! From d8717b3a0fabd8a3f4dcaeba857c47c567bc6827 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 09:25:20 -0400 Subject: [PATCH 27/42] Restructured discards in SyMBA to separate types of discards from each other. Also added particle number checks to coordinate conversion methods in order to simplify calls to them --- src/discard/discard.f90 | 17 +++++++------ src/symba/symba_collision.f90 | 1 + src/symba/symba_discard.f90 | 46 ++++++++++++++++++++++++++--------- src/util/util_coord.f90 | 6 +++++ 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/discard/discard.f90 b/src/discard/discard.f90 index 5f87ee752..f4244145a 100644 --- a/src/discard/discard.f90 +++ b/src/discard/discard.f90 @@ -38,6 +38,7 @@ module subroutine discard_pl(self, system, param) class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object class(swiftest_parameters), intent(in) :: param !! Current run configuration parameter + if (self%nbody == 0) return self%ldiscard(:) = .false. return @@ -58,17 +59,17 @@ module subroutine discard_tp(self, system, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parameter associate(tp => self, ntp => self%nbody, cb => system%cb, pl => system%pl, npl => system%pl%nbody) - if (ntp == 0) return + if ((ntp == 0) .or. (npl ==0)) return + if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. & (param%rmaxu >= 0.0_DP) .or. ((param%qmin >= 0.0_DP) .and. (param%qmin_coord == "BARY"))) then - if (npl > 0) call pl%h2b(cb) - if (ntp > 0) call tp%h2b(cb) - end if - if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. (param%rmaxu >= 0.0_DP)) then - if (ntp > 0) call discard_cb_tp(tp, system, param) + call pl%h2b(cb) + call tp%h2b(cb) end if - if (param%qmin >= 0.0_DP .and. ntp > 0) call discard_peri_tp(tp, system, param) - if (param%lclose .and. ntp > 0) call discard_pl_tp(tp, system, param) + + if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. (param%rmaxu >= 0.0_DP)) call discard_cb_tp(tp, system, param) + if (param%qmin >= 0.0_DP) call discard_peri_tp(tp, system, param) + if (param%lclose) call discard_pl_tp(tp, system, param) if (any(tp%ldiscard)) call tp%spill(system%tp_discards, tp%ldiscard, ldestructive=.true.) end associate diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index bb67508fd..66aa1ef30 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -142,6 +142,7 @@ pure elemental function symba_collision_check_one(xr, yr, zr, vxr, vyr, vzr, Gmt return end function symba_collision_check_one + module subroutine symba_collision_make_family_pl(self, idx) !! author: Jennifer L.L. Pouplin, Carlisle A. wishard, and David A. Minton !! diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index f9066fdc6..7d15d996b 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -3,14 +3,45 @@ contains module subroutine symba_discard_pl(self, system, param) + !! author: David A. Minton + !! + !! Call the various flavors of discards for massive bodies in SyMBA runs, including discards due to colling with the central body, + !! escaping the system, or colliding with each other. implicit none ! Arguments class(symba_pl), intent(inout) :: self !! SyMBA test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + call symba_discard_nonplpl(self, system, param) + + select type(param) + class is (symba_parameters) + if (param%lfragmentation) then + + end if + + end select + + return + end subroutine symba_discard_pl + + subroutine symba_discard_nonplpl(pl, system, param) + !! author: David A. Minton + !! + !! Check to see if planets should be discarded based on their positions or because they are unbound + !s + !! + !! Adapted from David E. Kaufmann's Swifter routine: symba_discard_pl.f90 + !! Adapted from Hal Levison's Swift routine discard_massive5.f + implicit none + ! Arguments + class(symba_pl), intent(inout) :: pl !! SyMBA test particle object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! First check for collisions with the central body - associate(pl => self, npl => self%nbody, cb => system%cb) + associate(npl => pl%nbody, cb => system%cb) if (npl == 0) return if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. & (param%rmaxu >= 0.0_DP) .or. ((param%qmin >= 0.0_DP) .and. (param%qmin_coord == "BARY"))) then @@ -22,16 +53,9 @@ module subroutine symba_discard_pl(self, system, param) if (param%qmin >= 0.0_DP .and. npl > 0) call symba_discard_peri_pl(pl, system, param) end associate - select type(param) - class is (symba_parameters) - if (param%lfragmentation) then - - end if - - end select - return - end subroutine symba_discard_pl + end subroutine symba_discard_nonplpl + subroutine symba_discard_cb_pl(pl, system, param) @@ -42,7 +66,7 @@ subroutine symba_discard_cb_pl(pl, system, param) !! its collisional status will be revoked. Discards due to colliding with or escaping the central body take precedence !! over pl-pl collisions !! - !! Adapted from David E. Kaufmann's Swifter routine: symba_discard_cb.f90 + !! Adapted from David E. Kaufmann's Swifter routine: symba_discard_sun.f90 !! Adapted from Hal Levison's Swift routine discard_massive5.f implicit none ! Arguments diff --git a/src/util/util_coord.f90 b/src/util/util_coord.f90 index 938d04951..ab5fe85df 100644 --- a/src/util/util_coord.f90 +++ b/src/util/util_coord.f90 @@ -18,6 +18,7 @@ module subroutine util_coord_h2b_pl(self, cb) real(DP) :: msys real(DP), dimension(NDIM) :: xtmp, vtmp + if (self%nbody == 0) return associate(pl => self, npl => self%nbody) msys = cb%Gmass xtmp(:) = 0.0_DP @@ -51,6 +52,7 @@ module subroutine util_coord_h2b_tp(self, cb) class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object class(swiftest_cb), intent(in) :: cb !! Swiftest central body object + if (self%nbody == 0) return associate(ntp => self%nbody, xbcb => cb%xb, vbcb => cb%vb, status => self%status, & xb => self%xb, xh => self%xh, vb => self%vb, vh => self%vh) @@ -83,6 +85,8 @@ module subroutine util_coord_b2h_pl(self, cb) ! Internals integer(I4B) :: i + if (self%nbody == 0) return + associate(npl => self%nbody, xbcb => cb%xb, vbcb => cb%vb, xb => self%xb, xh => self%xh, & vb => self%vb, vh => self%vh) do i = 1, NDIM @@ -107,6 +111,8 @@ module subroutine util_coord_b2h_tp(self, cb) class(swiftest_tp), intent(inout) :: self !! Swiftest massive body object class(swiftest_cb), intent(in) :: cb !! Swiftest central body object + if (self%nbody == 0) return + associate(ntp => self%nbody, xbcb => cb%xb, vbcb => cb%vb, xb => self%xb, xh => self%xh, & vb => self%vb, vh => self%vh, status => self%status) where(status(1:ntp) /= INACTIVE) From 8a3c43cf198daa7f0b3fccbdd19a412eab7e6a9c Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 10:03:08 -0400 Subject: [PATCH 28/42] Refactored msys to system%Gmtot. Added back the massive body pericenter check (originally symba_peri.f90 and symba_discard_peri_pl.f90 from Swifter. Now symba_util_peri_pl bound to the get_peri method call, and symba_discard_peri_pl --- src/discard/discard.f90 | 4 +- src/helio/helio_coord.f90 | 6 +- src/modules/swiftest_classes.f90 | 2 +- src/modules/symba_classes.f90 | 9 ++ src/symba/symba_discard.f90 | 147 ++++++++++++++++++------------- src/symba/symba_util.f90 | 87 ++++++++++++++++++ src/util/util_coord.f90 | 10 +-- src/util/util_peri.f90 | 2 +- src/util/util_set.f90 | 2 +- 9 files changed, 197 insertions(+), 72 deletions(-) diff --git a/src/discard/discard.f90 b/src/discard/discard.f90 index f4244145a..7dbbd95c2 100644 --- a/src/discard/discard.f90 +++ b/src/discard/discard.f90 @@ -94,7 +94,7 @@ subroutine discard_cb_tp(tp, system, param) integer(I4B) :: i real(DP) :: energy, vb2, rb2, rh2, rmin2, rmax2, rmaxu2 - associate(ntp => tp%nbody, cb => system%cb, t => param%t, msys => system%msys) + associate(ntp => tp%nbody, cb => system%cb, t => param%t, Gmtot => system%Gmtot) rmin2 = max(param%rmin * param%rmin, cb%radius * cb%radius) rmax2 = param%rmax**2 rmaxu2 = param%rmaxu**2 @@ -114,7 +114,7 @@ subroutine discard_cb_tp(tp, system, param) else if (param%rmaxu >= 0.0_DP) then rb2 = dot_product(tp%xb(:, i), tp%xb(:, i)) vb2 = dot_product(tp%vb(:, i), tp%vb(:, i)) - energy = 0.5_DP * vb2 - msys / sqrt(rb2) + energy = 0.5_DP * vb2 - Gmtot / sqrt(rb2) if ((energy > 0.0_DP) .and. (rb2 > rmaxu2)) then tp%status(i) = DISCARDED_RMAXU write(*, *) "Particle ", tp%id(i), " is unbound and too far from barycenter at t = ", t diff --git a/src/helio/helio_coord.f90 b/src/helio/helio_coord.f90 index 0e58a3ab6..f40781810 100644 --- a/src/helio/helio_coord.f90 +++ b/src/helio/helio_coord.f90 @@ -68,14 +68,14 @@ module subroutine helio_coord_vh2vb_pl(self, cb) class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object ! Internals integer(I4B) :: i - real(DP) :: msys + real(DP) :: Gmtot if (self%nbody == 0) return associate(pl => self, npl => self%nbody) - msys = cb%Gmass + sum(pl%Gmass(1:npl)) + Gmtot = cb%Gmass + sum(pl%Gmass(1:npl)) do i = 1, NDIM - cb%vb(i) = -sum(pl%Gmass(1:npl) * pl%vh(i, 1:npl)) / msys + cb%vb(i) = -sum(pl%Gmass(1:npl) * pl%vh(i, 1:npl)) / Gmtot pl%vb(i, 1:npl) = pl%vh(i, 1:npl) + cb%vb(i) end do end associate diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index fdb2360ee..c30947d68 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -259,7 +259,7 @@ module swiftest_classes 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 - real(DP) :: msys = 0.0_DP !! Total system mass - used for barycentric coordinate conversion + real(DP) :: Gmtot = 0.0_DP !! Total system mass - used for barycentric coordinate conversion real(DP) :: ke = 0.0_DP !! System kinetic energy real(DP) :: pe = 0.0_DP !! System potential energy real(DP) :: te = 0.0_DP !! System total energy diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 92caa0bb3..c60b2a838 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -94,6 +94,7 @@ module symba_classes procedure :: setup => symba_setup_pl !! Constructor method - Allocates space for number of particle procedure :: append => symba_util_append_pl !! Appends elements from one structure to another procedure :: fill => symba_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) + procedure :: get_peri => symba_util_peri_pl !! Determine system pericenter passages for massive bodies procedure :: resize => symba_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. procedure :: sort => symba_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods @@ -479,6 +480,14 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) class(swiftest_body), intent(in) :: inserts !! Inserted object logical, dimension(:), intent(in) :: lfill_list !! Logical array of bodies to merge into the keeps end subroutine symba_util_fill_tp + + module subroutine symba_util_peri_pl(self, system, param) + use swiftest_classes, only : swiftest_nbody_system, swiftest_parameters + implicit none + class(symba_pl), intent(inout) :: self !! SyMBA massive body object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + end subroutine symba_util_peri_pl end interface interface util_resize diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 7d15d996b..a84e158d3 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -2,62 +2,6 @@ use swiftest contains - module subroutine symba_discard_pl(self, system, param) - !! author: David A. Minton - !! - !! Call the various flavors of discards for massive bodies in SyMBA runs, including discards due to colling with the central body, - !! escaping the system, or colliding with each other. - implicit none - ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA test particle object - class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - - call symba_discard_nonplpl(self, system, param) - - select type(param) - class is (symba_parameters) - if (param%lfragmentation) then - - end if - - end select - - return - end subroutine symba_discard_pl - - subroutine symba_discard_nonplpl(pl, system, param) - !! author: David A. Minton - !! - !! Check to see if planets should be discarded based on their positions or because they are unbound - !s - !! - !! Adapted from David E. Kaufmann's Swifter routine: symba_discard_pl.f90 - !! Adapted from Hal Levison's Swift routine discard_massive5.f - implicit none - ! Arguments - class(symba_pl), intent(inout) :: pl !! SyMBA test particle object - class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - - ! First check for collisions with the central body - associate(npl => pl%nbody, cb => system%cb) - if (npl == 0) return - if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. & - (param%rmaxu >= 0.0_DP) .or. ((param%qmin >= 0.0_DP) .and. (param%qmin_coord == "BARY"))) then - call pl%h2b(cb) - end if - if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. (param%rmaxu >= 0.0_DP)) then - call symba_discard_cb_pl(pl, system, param) - end if - if (param%qmin >= 0.0_DP .and. npl > 0) call symba_discard_peri_pl(pl, system, param) - end associate - - return - end subroutine symba_discard_nonplpl - - - subroutine symba_discard_cb_pl(pl, system, param) !! author: David A. Minton !! @@ -98,7 +42,7 @@ subroutine symba_discard_cb_pl(pl, system, param) else if (param%rmaxu >= 0.0_DP) then rb2 = dot_product(pl%xb(:,i), pl%xb(:,i)) vb2 = dot_product(pl%vb(:,i), pl%vb(:,i)) - energy = 0.5_DP * vb2 - system%msys / sqrt(rb2) + energy = 0.5_DP * vb2 - system%Gmtot / sqrt(rb2) if ((energy > 0.0_DP) .and. (rb2 > rmaxu2)) then pl%ldiscard(i) = .true. pl%lcollision(i) = .false. @@ -114,19 +58,104 @@ subroutine symba_discard_cb_pl(pl, system, param) end subroutine symba_discard_cb_pl + subroutine symba_discard_nonplpl(pl, system, param) + !! author: David A. Minton + !! + !! Check to see if planets should be discarded based on their positions or because they are unbound + !s + !! + !! Adapted from David E. Kaufmann's Swifter routine: symba_discard_pl.f90 + !! Adapted from Hal Levison's Swift routine discard_massive5.f + implicit none + ! Arguments + class(symba_pl), intent(inout) :: pl !! SyMBA test particle object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + + ! First check for collisions with the central body + associate(npl => pl%nbody, cb => system%cb) + if (npl == 0) return + if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. & + (param%rmaxu >= 0.0_DP) .or. ((param%qmin >= 0.0_DP) .and. (param%qmin_coord == "BARY"))) then + call pl%h2b(cb) + end if + if ((param%rmin >= 0.0_DP) .or. (param%rmax >= 0.0_DP) .or. (param%rmaxu >= 0.0_DP)) then + call symba_discard_cb_pl(pl, system, param) + end if + if (param%qmin >= 0.0_DP .and. npl > 0) call symba_discard_peri_pl(pl, system, param) + end associate + + return + end subroutine symba_discard_nonplpl + + subroutine symba_discard_peri_pl(pl, system, param) !! author: David A. Minton !! !! Check to see if a test particle should be discarded because its perihelion distance becomes too small !! - !! Adapted from David E. Kaufmann's Swifter routine: discard_peri.f90 - !! Adapted from Hal Levison's Swift routine discard_peri.f + !! Adapted from David E. Kaufmann's Swifter routine: symba_discard_peri_pl.f90 + !! Adapted from Hal Levison's Swift routine discard_mass_peri.f implicit none ! Arguments class(symba_pl), intent(inout) :: pl !! SyMBA massive body object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + logical, save :: lfirst = .true. + logical :: lfirst_orig + integer(I4B) :: i + + + lfirst_orig = pl%lfirst + pl%lfirst = lfirst + if (lfirst) then + call pl%get_peri(system, param) + lfirst = .false. + else + call pl%get_peri(system, param) + do i = 1, pl%nbody + if (pl%status(i) == ACTIVE) then + if ((pl%isperi(i) == 0) .and. (pl%nplenc(i)== 0)) then + if ((pl%atp(i) >= param%qmin_alo) .and. (pl%atp(i) <= param%qmin_ahi) .and. (pl%peri(i) <= param%qmin)) then + pl%ldiscard(i) = .true. + pl%lcollision(i) = .false. + pl%status(i) = DISCARDED_PERI + write(*, *) "Particle ", pl%id(i), " perihelion distance too small at t = ", param%t + end if + end if + end if + end do + end if + pl%lfirst = lfirst_orig + return + end subroutine symba_discard_peri_pl + + module subroutine symba_discard_pl(self, system, param) + !! author: David A. Minton + !! + !! Call the various flavors of discards for massive bodies in SyMBA runs, including discards due to colling with the central body, + !! escaping the system, or colliding with each other. + implicit none + ! Arguments + class(symba_pl), intent(inout) :: self !! SyMBA test particle object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + + call symba_discard_nonplpl(self, system, param) + + select type(param) + class is (symba_parameters) + if (param%lfragmentation) then + + end if + + end select + + return + end subroutine symba_discard_pl + end submodule s_symba_discard \ No newline at end of file diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index feda27a07..7050bf050 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -271,6 +271,92 @@ module subroutine symba_util_fill_tp(self, inserts, lfill_list) end subroutine symba_util_fill_tp + module subroutine symba_util_peri_pl(self, system, param) + !! author: David A. Minton + !! + !! Determine system pericenter passages for planets in SyMBA + !! + !! Adapted from David E. Kaufmann's Swifter routine: symba_peri.f90 + !! Adapted from Hal Levison's Swift routine util_mass_peri.f + implicit none + ! Arguments + class(symba_pl), intent(inout) :: self !! SyMBA massive body object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + integer(I4B) :: i + real(DP) :: vdotr, e + + associate(pl => self, npl => self%nbody) + if (pl%lfirst) then + if (param%qmin_coord == "HELIO") then + do i = 1, npl + if (pl%status(i) == ACTIVE) then + vdotr = dot_product(pl%xh(:,i), pl%vh(:,i)) + if (vdotr > 0.0_DP) then + pl%isperi(i) = 1 + else + pl%isperi(i) = -1 + end if + end if + end do + else + do i = 1, npl + if (pl%status(i) == ACTIVE) then + vdotr = dot_product(pl%xb(:,i), pl%vb(:,i)) + if (vdotr > 0.0_DP) then + pl%isperi(i) = 1 + else + pl%isperi(i) = -1 + end if + end if + end do + end if + else + if (param%qmin_coord == "HELIO") then + do i = 1, npl + if (pl%status(i) == ACTIVE) then + vdotr = dot_product(pl%xh(:,i), pl%vh(:,i)) + if (pl%isperi(i) == -1) then + if (vdotr >= 0.0_DP) then + pl%isperi(i) = 0 + CALL orbel_xv2aeq(pl%mu(i), pl%xh(:,i), pl%vh(:,i), pl%atp(i), e, pl%peri(i)) + end if + else + if (vdotr > 0.0_DP) then + pl%isperi(i) = 1 + else + pl%isperi(i) = -1 + end if + end if + end if + end do + else + do i = 1, npl + if (pl%status(i) == ACTIVE) then + vdotr = dot_product(pl%xb(:,i), pl%vb(:,i)) + if (pl%isperi(i) == -1) then + if (vdotr >= 0.0_DP) then + pl%isperi(i) = 0 + CALL orbel_xv2aeq(system%Gmtot, pl%xb(:,i), pl%vb(:,i), pl%atp(i), e, pl%peri(i)) + end if + else + if (vdotr > 0.0_DP) then + pl%isperi(i) = 1 + else + pl%isperi(i) = -1 + end if + end if + end if + end do + end if + end if + end associate + + return + end subroutine symba_util_peri_pl + + module subroutine symba_util_resize_arr_info(arr, nnew) !! author: David A. Minton !! @@ -385,6 +471,7 @@ module subroutine symba_util_resize_tp(self, nnew) return end subroutine symba_util_resize_tp + module subroutine symba_util_sort_pl(self, sortby, ascending) !! author: David A. Minton !! diff --git a/src/util/util_coord.f90 b/src/util/util_coord.f90 index ab5fe85df..c10dbace7 100644 --- a/src/util/util_coord.f90 +++ b/src/util/util_coord.f90 @@ -15,21 +15,21 @@ module subroutine util_coord_h2b_pl(self, cb) class(swiftest_cb), intent(inout) :: cb !! Swiftest central body object ! Internals integer(I4B) :: i - real(DP) :: msys + real(DP) :: Gmtot real(DP), dimension(NDIM) :: xtmp, vtmp if (self%nbody == 0) return associate(pl => self, npl => self%nbody) - msys = cb%Gmass + Gmtot = cb%Gmass xtmp(:) = 0.0_DP vtmp(:) = 0.0_DP do i = 1, npl - msys = msys + pl%Gmass(i) + Gmtot = Gmtot + pl%Gmass(i) xtmp(:) = xtmp(:) + pl%Gmass(i) * pl%xh(:,i) vtmp(:) = vtmp(:) + pl%Gmass(i) * pl%vh(:,i) end do - cb%xb(:) = -xtmp(:) / msys - cb%vb(:) = -vtmp(:) / msys + cb%xb(:) = -xtmp(:) / Gmtot + cb%vb(:) = -vtmp(:) / Gmtot do i = 1, npl pl%xb(:,i) = pl%xh(:,i) + cb%xb(:) pl%vb(:,i) = pl%vh(:,i) + cb%vb(:) diff --git a/src/util/util_peri.f90 b/src/util/util_peri.f90 index 407ee5097..66f2254e1 100644 --- a/src/util/util_peri.f90 +++ b/src/util/util_peri.f90 @@ -45,7 +45,7 @@ module subroutine util_peri_tp(self, system, param) if (tp%isperi(i) == -1) then if (vdotr(i) >= 0.0_DP) then tp%isperi(i) = 0 - call orbel_xv2aeq(system%msys, tp%xb(:, i), tp%vb(:, i), tp%atp(i), e, tp%peri(i)) + call orbel_xv2aeq(system%Gmtot, tp%xb(:, i), tp%vb(:, i), tp%atp(i), e, tp%peri(i)) end if else if (vdotr(i) > 0.0_DP) then diff --git a/src/util/util_set.f90 b/src/util/util_set.f90 index a1c4075b6..86e021ab6 100644 --- a/src/util/util_set.f90 +++ b/src/util/util_set.f90 @@ -62,7 +62,7 @@ module subroutine util_set_msys(self) ! Arguments class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nobdy system object - self%msys = self%cb%Gmass + sum(self%pl%Gmass(1:self%pl%nbody), self%pl%status(1:self%pl%nbody) /= INACTIVE) + self%Gmtot = self%cb%Gmass + sum(self%pl%Gmass(1:self%pl%nbody), self%pl%status(1:self%pl%nbody) /= INACTIVE) return end subroutine util_set_msys From 9f5621c653294a87eea7732c75775ae045878276 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 10:46:43 -0400 Subject: [PATCH 29/42] Wrote template for an encounter scrub method that will make use of part of the code in the symba_collision.f90 subroutine in the current Fragmentation branch --- src/modules/symba_classes.f90 | 10 +++++++++- src/symba/symba_collision.f90 | 16 ++++++++++++++++ src/symba/symba_discard.f90 | 14 +++++--------- 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index c60b2a838..ee032c7f3 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -142,6 +142,7 @@ module symba_classes !> SyMBA class for tracking pl-pl close encounters in a step type, extends(symba_pltpenc) :: symba_plplenc contains + procedure :: scrub_non_collision => symba_collision_encounter_scrub !! Processes the pl-pl encounter list remove only those encounters that led to a collisio end type symba_plplenc !******************************************************************************************************************************** @@ -175,6 +176,13 @@ module subroutine symba_collision_check_pltpenc(self, system, param, t, dt, irec integer(I4B), intent(in) :: irec !! Current recursion level end subroutine symba_collision_check_pltpenc + module subroutine symba_collision_encounter_scrub(self, system, param) + implicit none + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameterss + end subroutine + module subroutine symba_collision_make_family_pl(self,idx) implicit none class(symba_pl), intent(inout) :: self !! SyMBA massive body object @@ -259,7 +267,7 @@ end subroutine symba_io_dump_particle_info module subroutine symba_io_param_reader(self, unit, iotype, v_list, iostat, iomsg) implicit none - class(symba_parameters), intent(inout) :: self !! Collection of parameters + class(symba_parameters), intent(inout) :: self !! Collection of SyMBA parameters integer, intent(in) :: unit !! File unit number character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT. !! If you do not include a char-literal-constant, the iotype argument contains only DT. diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 66aa1ef30..5cc886485 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -204,4 +204,20 @@ module subroutine symba_collision_make_family_pl(self, idx) return end subroutine symba_collision_make_family_pl + module subroutine symba_collision_encounter_scrub(self, system, param) + !! author: David A. Minton + !! + !! Processes the pl-pl encounter list remove only those encounters that led to a collision + !! + implicit none + ! Arguments + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + + return + end subroutine + + end submodule s_symba_collision \ No newline at end of file diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index a84e158d3..f5e397548 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -144,15 +144,11 @@ module subroutine symba_discard_pl(self, system, param) class(symba_pl), intent(inout) :: self !! SyMBA test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - - call symba_discard_nonplpl(self, system, param) - - select type(param) - class is (symba_parameters) - if (param%lfragmentation) then - - end if - + + select type(system) + class is (symba_nbody_system) + call symba_discard_nonplpl(self, system, param) + call system%plplenc_list%scrub_non_collision(system, param) end select return From 15c1d9c46a02cafc0257bda1332aba5c69456483 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 12:17:22 -0400 Subject: [PATCH 30/42] Added in code for scrubbing out the non-colliding encounters from the plplenc_list object --- src/modules/swiftest_classes.f90 | 15 ++++-- src/modules/symba_classes.f90 | 18 ++++--- src/symba/symba_collision.f90 | 84 ++++++++++++++++++++++++++------ src/symba/symba_util.f90 | 48 ++++++++++-------- src/util/util_resize.f90 | 3 ++ src/util/util_spill.f90 | 33 +++++++++++++ 6 files changed, 155 insertions(+), 46 deletions(-) diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index c30947d68..0fe43e391 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -297,9 +297,10 @@ module swiftest_classes real(DP), dimension(:,:), allocatable :: v1 !! the velocity of body 1 in the encounter real(DP), dimension(:,:), allocatable :: v2 !! the velocity of body 2 in the encounter contains - procedure :: copy => util_copy_encounter - procedure :: resize => util_resize_encounter - procedure :: setup => setup_encounter + procedure :: setup => setup_encounter !! A constructor that sets the number of encounters and allocates and initializes all arrays + procedure :: copy => util_copy_encounter !! Copies elements from the source encounter list into self. + procedure :: spill => util_spill_encounter !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) + procedure :: resize => util_resize_encounter !! Checks the current size of the encounter list against the required size and extends it by a factor of 2 more than requested if it is too small. end type swiftest_encounter abstract interface @@ -1152,6 +1153,14 @@ module subroutine util_spill_body(self, discards, lspill_list, ldestructive) logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine util_spill_body + module subroutine util_spill_encounter(self, discards, lspill_list, ldestructive) + implicit none + class(swiftest_encounter), intent(inout) :: self !! Swiftest encounter list + class(swiftest_encounter), 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 + end subroutine util_spill_encounter + module subroutine util_spill_pl(self, discards, lspill_list, ldestructive) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index ee032c7f3..d682020ae 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -133,7 +133,7 @@ module symba_classes procedure :: encounter_check => symba_encounter_check_pltpenc !! Checks if massive bodies are going through close encounters with each other procedure :: kick => symba_kick_pltpenc !! Kick barycentric velocities of active test particles within SyMBA recursion procedure :: setup => symba_setup_pltpenc !! A constructor that sets the number of encounters and allocates and initializes all arrays - procedure :: copy => symba_util_copy_pltpenc !! Copies all elements of one pltpenc list to another + procedure :: spill => symba_util_spill_pltpenc !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type symba_pltpenc !******************************************************************************************************************************** @@ -447,13 +447,6 @@ module subroutine symba_util_append_tp(self, source, lsource_mask) class(swiftest_body), intent(in) :: source !! Source object to append logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to end subroutine symba_util_append_tp - - module subroutine symba_util_copy_pltpenc(self, source) - use swiftest_classes, only : swiftest_encounter - implicit none - class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - class(swiftest_encounter), intent(in) :: source !! Source object to copy into - end subroutine symba_util_copy_pltpenc end interface interface util_fill @@ -580,6 +573,15 @@ module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) logical, intent(in) :: ldestructive !! Logical flag indicating whether or not this operation should alter the keeps array or not end subroutine symba_util_spill_pl + module subroutine symba_util_spill_pltpenc(self, discards, lspill_list, ldestructive) + use swiftest_classes, only : swiftest_encounter + implicit none + class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list + class(swiftest_encounter), 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 + end subroutine symba_util_spill_pltpenc + module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) use swiftest_classes, only : swiftest_body implicit none diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 5cc886485..739ca9778 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -143,6 +143,74 @@ pure elemental function symba_collision_check_one(xr, yr, zr, vxr, vyr, vzr, Gmt end function symba_collision_check_one + module subroutine symba_collision_encounter_scrub(self, system, param) + !! author: David A. Minton + !! + !! Processes the pl-pl encounter list remove only those encounters that led to a collision + !! + implicit none + ! Arguments + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + logical, dimension(self%nenc) :: lplpl_collision + logical, dimension(:), allocatable :: lplpl_unique_parent + integer(I4B), dimension(:), pointer :: plparent + integer(I4B), dimension(:), allocatable :: collision_idx, unique_parent_idx + integer(I4B) :: i, index_coll, ncollisions, nunique_parent + type(symba_plplenc) :: plplenc_noncollision + + + select type (pl => system%pl) + class is (symba_pl) + associate(plplenc_list => self, nplplenc => self%nenc, idx1 => self%index1, idx2 => self%index2, plparent => pl%kin%parent) + lplpl_collision(:) = plplenc_list%status(1:nplplenc) == COLLISION + if (.not.any(lplpl_collision)) return + + ! Get the subset of pl-pl encounters that lead to a collision + ncollisions = count(lplpl_collision(:)) + allocate(collision_idx(ncollisions)) + collision_idx = pack([(i, i=1, nplplenc)], lplpl_collision) + + ! Get the subset of collisions that involve a unique pair of parents + allocate(lplpl_unique_parent(ncollisions)) + + lplpl_unique_parent(:) = plparent(idx1(collision_idx(:))) /= plparent(idx2(collision_idx(:))) + nunique_parent = count(lplpl_unique_parent(:)) + allocate(unique_parent_idx(nunique_parent)) + unique_parent_idx = pack(collision_idx(:), lplpl_unique_parent(:)) + + ! Scrub all pl-pl collisions involving unique pairs of parents, which will remove all duplicates and leave behind + ! all pairs that have themselves as parents but are not part of the unique parent list. This can hapepn in rare cases + ! due to restructuring of parent/child relationships when there are large numbers of multi-body collisions in a single + ! step + lplpl_unique_parent(:) = .true. + do index_coll = 1, ncollisions + associate(ip1 => plparent(idx1(collision_idx(index_coll))), ip2 => plparent(idx2(collision_idx(index_coll)))) + lplpl_unique_parent(:) = .not. ( any(plparent(idx1(unique_parent_idx(:))) == ip1) .or. & + any(plparent(idx2(unique_parent_idx(:))) == ip1) .or. & + any(plparent(idx1(unique_parent_idx(:))) == ip2) .or. & + any(plparent(idx2(unique_parent_idx(:))) == ip2) ) + end associate + end do + + ! Reassemble collision index list to include only those containing the unique pairs of parents, plus all the non-unique pairs that don't + ! contain a parent body on the unique parent list. + ncollisions = nunique_parent + count(lplpl_unique_parent) + collision_idx = [unique_parent_idx(:), pack(collision_idx(:), lplpl_unique_parent(:))] + + ! Create a mask that contains only the pl-pl encounters that did not result in a collision, and then discard them + lplpl_collision(:) = .true. + lplpl_collision(collision_idx(:)) = .false. + call plplenc_list%spill(plplenc_noncollision, lplpl_collision, ldestructive = .true.) + end associate + end select + + return + end subroutine symba_collision_encounter_scrub + + module subroutine symba_collision_make_family_pl(self, idx) !! author: Jennifer L.L. Pouplin, Carlisle A. wishard, and David A. Minton !! @@ -204,20 +272,4 @@ module subroutine symba_collision_make_family_pl(self, idx) return end subroutine symba_collision_make_family_pl - module subroutine symba_collision_encounter_scrub(self, system, param) - !! author: David A. Minton - !! - !! Processes the pl-pl encounter list remove only those encounters that led to a collision - !! - implicit none - ! Arguments - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list - class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - ! Internals - - return - end subroutine - - end submodule s_symba_collision \ No newline at end of file diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 7050bf050..56eaacc2c 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -142,25 +142,6 @@ module subroutine symba_util_append_tp(self, source, lsource_mask) return end subroutine symba_util_append_tp - module subroutine symba_util_copy_pltpenc(self, source) - !! author: David A. Minton - !! - !! Copies elements from the source encounter list into self. - implicit none - ! Arguments - class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list - class(swiftest_encounter), intent(in) :: source !! Source object to copy into - - call util_copy_encounter(self, source) - associate(n => source%nenc) - select type(source) - class is (symba_pltpenc) - self%level(1:n) = source%level(1:n) - end select - end associate - - return - end subroutine symba_util_copy_pltpenc module subroutine symba_util_fill_arr_info(keeps, inserts, lfill_list) !! author: David A. Minton @@ -730,6 +711,35 @@ module subroutine symba_util_spill_pl(self, discards, lspill_list, ldestructive) end subroutine symba_util_spill_pl + module subroutine symba_util_spill_pltpenc(self, discards, lspill_list, ldestructive) + !! author: David A. Minton + !! + !! Move spilled (discarded) SyMBA encounter structure from active list to discard list + !! Note: Because the symba_plplenc currently does not contain any additional variable components, this method can recieve it as an input as well. + implicit none + ! Arguments + class(symba_pltpenc), intent(inout) :: self !! SyMBA pl-tp encounter list + class(swiftest_encounter), 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 + ! Internals + integer(I4B) :: i + + associate(keeps => self) + select type(discards) + class is (symba_pltpenc) + call util_spill(keeps%level, discards%level, lspill_list, ldestructive) + call util_spill_encounter(keeps, discards, lspill_list, ldestructive) + class default + write(*,*) "Invalid object passed to the spill method. Source must be of class symba_pltpenc or its descendents!" + call util_exit(FAILURE) + end select + end associate + + return + end subroutine symba_util_spill_pltpenc + + module subroutine symba_util_spill_tp(self, discards, lspill_list, ldestructive) !! author: David A. Minton !! diff --git a/src/util/util_resize.f90 b/src/util/util_resize.f90 index 3772a8207..c6d5aa34f 100644 --- a/src/util/util_resize.f90 +++ b/src/util/util_resize.f90 @@ -211,6 +211,9 @@ module subroutine util_resize_encounter(self, nnew) !! author: David A. Minton !! !! Checks the current size of the encounter list 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(swiftest_encounter), intent(inout) :: self !! Swiftest encounter list diff --git a/src/util/util_spill.f90 b/src/util/util_spill.f90 index 5f942854a..fc945765c 100644 --- a/src/util/util_spill.f90 +++ b/src/util/util_spill.f90 @@ -194,6 +194,39 @@ module subroutine util_spill_body(self, discards, lspill_list, ldestructive) return end subroutine util_spill_body + module subroutine util_spill_encounter(self, discards, lspill_list, ldestructive) + !! author: David A. Minton + !! + !! Move spilled (discarded) Swiftest encounter structure from active list to discard list + implicit none + ! Arguments + class(swiftest_encounter), intent(inout) :: self !! Swiftest encounter list + class(swiftest_encounter), 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 + ! Internals + integer(I4B) :: i + + associate(keeps => self) + + call util_spill(keeps%lvdotr, discards%lvdotr, lspill_list, ldestructive) + call util_spill(keeps%status, discards%status, lspill_list, ldestructive) + call util_spill(keeps%index1, discards%index1, lspill_list, ldestructive) + call util_spill(keeps%index2, discards%index2, lspill_list, ldestructive) + call util_spill(keeps%x1, discards%x1, lspill_list, ldestructive) + call util_spill(keeps%x2, discards%x2, lspill_list, ldestructive) + call util_spill(keeps%v1, discards%v1, lspill_list, ldestructive) + call util_spill(keeps%v2, discards%v2, lspill_list, ldestructive) + + ! This is the base class, so will be the last to be called in the cascade. + ! Therefore we need to set the nenc values for both the keeps and discareds + discards%nenc = count(lspill_list(:)) + keeps%nenc = count(.not.lspill_list(:)) + end associate + + return + end subroutine util_spill_encounter + module subroutine util_spill_pl(self, discards, lspill_list, ldestructive) !! author: David A. Minton From fdd2cf9ec24c4860f597152705135594007d3c0b Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 12:33:10 -0400 Subject: [PATCH 31/42] Added in template methods for resolving fragmentations and mergers --- src/modules/symba_classes.f90 | 18 +++++++++++++++++- src/symba/symba_collision.f90 | 32 ++++++++++++++++++++++++++++++++ src/symba/symba_discard.f90 | 15 +++++++++++++-- 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index d682020ae..88c973aee 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -142,7 +142,9 @@ module symba_classes !> SyMBA class for tracking pl-pl close encounters in a step type, extends(symba_pltpenc) :: symba_plplenc contains - procedure :: scrub_non_collision => symba_collision_encounter_scrub !! Processes the pl-pl encounter list remove only those encounters that led to a collisio + procedure :: scrub_non_collision => symba_collision_encounter_scrub !! Processes the pl-pl encounter list remove only those encounters that led to a collision + procedure :: resolve_fragmentations => symba_collision_resolve_fragmentations !! Process list of collisions, determine the collisional regime, and then create fragments + procedure :: resolve_mergers => symba_collision_resolve_mergers !! Process list of collisions and merge colliding bodies together end type symba_plplenc !******************************************************************************************************************************** @@ -189,6 +191,20 @@ module subroutine symba_collision_make_family_pl(self,idx) integer(I4B), dimension(2), intent(in) :: idx !! Array holding the indices of the two bodies involved in the collision end subroutine symba_collision_make_family_pl + module subroutine symba_collision_resolve_fragmentations(self, system, param) + implicit none + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions + end subroutine symba_collision_resolve_fragmentations + + module subroutine symba_collision_resolve_mergers(self, system, param) + implicit none + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions + end subroutine symba_collision_resolve_mergers + module subroutine symba_discard_pl(self, system, param) use swiftest_classes, only : swiftest_nbody_system, swiftest_parameters implicit none diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 739ca9778..11175fe3a 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -272,4 +272,36 @@ module subroutine symba_collision_make_family_pl(self, idx) return end subroutine symba_collision_make_family_pl + + module subroutine symba_collision_resolve_fragmentations(self, system, param) + !! author: David A. Minton + !! + !! Process list of collisions, determine the collisional regime, and then create fragments. + !! + implicit none + ! Arguments + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions + ! Internals + + return + end subroutine symba_collision_resolve_fragmentations + + + module subroutine symba_collision_resolve_mergers(self, system, param) + !! author: David A. Minton + !! + !! Process list of collisions and merge colliding bodies together. + !! + implicit none + ! Arguments + class(symba_plplenc), intent(inout) :: self !! SyMBA pl-pl encounter list + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions + ! Internals + + return + end subroutine symba_collision_resolve_mergers + end submodule s_symba_collision \ No newline at end of file diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index f5e397548..57b26e8ea 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -147,8 +147,19 @@ module subroutine symba_discard_pl(self, system, param) select type(system) class is (symba_nbody_system) - call symba_discard_nonplpl(self, system, param) - call system%plplenc_list%scrub_non_collision(system, param) + select type(param) + class is (symba_parameters) + associate(pl => self, plplenc_list => system%plplenc_list) + call symba_discard_nonplpl(self, system, param) + call plplenc_list%scrub_non_collision(system, param) + call pl%h2b(system%cb) + if (param%lfragmentation) then + call plplenc_list%resolve_fragmentations(system, param) + else + call plplenc_list%resolve_mergers(system, param) + end if + end associate + end select end select return From 8c8c8a0d400cf92b89055a05298bce81815f116b Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 13:24:28 -0400 Subject: [PATCH 32/42] Added in the family consolidation code --- src/symba/symba_collision.f90 | 118 ++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 11175fe3a..13c874b0f 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -143,6 +143,124 @@ pure elemental function symba_collision_check_one(xr, yr, zr, vxr, vyr, vzr, Gmt end function symba_collision_check_one + function symba_collision_consolidate_familes(pl, idx_parent, family, x, v, mass, radius, L_spin, Ip) result(lflag) + !! author: David A. Minton + !! + !! Loops through the pl-pl collision list and groups families together by index. Outputs the indices of all family members, + !! and pairs of quantities (x and v vectors, mass, radius, L_spin, and Ip) that can be used to resolve the collisional outcome. + implicit none + ! Arguments + class(symba_pl), intent(inout) :: pl !! SyMBA massive body object + integer(I4B), dimension(2), intent(inout) :: idx_parent !! Index of the two bodies considered the "parents" of the collision + integer(I4B), dimension(:), allocatable, intent(out) :: family !! List of indices of all bodies inovlved in the collision + real(DP), dimension(NDIM,2), intent(out) :: x, v, L_spin, Ip !! Output values that represent a 2-body equivalent of a possibly 2+ body collision + real(DP), dimension(2), intent(out) :: mass, radius !! Output values that represent a 2-body equivalent of a possibly 2+ body collision + ! Result + logical :: lflag !! Logical flag indicating whether a family was successfully created or not + ! Internals + type family_array + integer(I4B), dimension(:), allocatable :: id + integer(I4B), dimension(:), allocatable :: idx + end type family_array + type(family_array), dimension(2) :: parent_child_index_array + integer(I4B), dimension(2) :: nchild + integer(I4B) :: i, j, fam_size, idx_child + real(DP), dimension(2) :: volume, density + real(DP) :: mchild, mtot, volchild + real(DP), dimension(NDIM) :: xc, vc, xcom, vcom, xchild, vchild, xcrossv + + nchild(:) = pl%kin(idx_parent(:))%nchild + ! If all of these bodies share a parent, but this is still a unique collision, move the last child + ! out of the parent's position and make it the secondary body + if (idx_parent(1) == idx_parent(2)) then + if (nchild(1) == 0) then ! There is only one valid body recorded in this pair (this could happen due to restructuring of the kinship relationships, though it should be rare) + lflag = .false. + return + end if + idx_parent(2) = pl%kin(idx_parent(1))%child(nchild(1)) + nchild(1) = nchild(1) - 1 + nchild(2) = 0 + pl%kin(idx_parent(:))%nchild = nchild(:) + pl%kin(idx_parent(2))%parent = idx_parent(1) + end if + + mass(:) = pl%mass(idx_parent(:)) ! Note: This is meant to mass, not G*mass, as the collisional regime determination uses mass values that will be converted to Si + radius(:) = pl%radius(idx_parent(:)) + volume(:) = (4.0_DP / 3.0_DP) * PI * radius(:)**3 + + ! Group together the ids and indexes of each collisional parent and its children + do j = 1, 2 + allocate(parent_child_index_array(j)%idx(nchild(j)+ 1)) + allocate(parent_child_index_array(j)%id(nchild(j)+ 1)) + associate(idx_arr => parent_child_index_array(j)%idx, & + id_arr => parent_child_index_array(j)%id, & + ncj => nchild(j), & + pl => pl, & + plkinj => pl%kin(idx_parent(j))) + idx_arr(1) = idx_parent(j) + if (ncj > 0) idx_arr(2:ncj + 1) = plkinj%child(1:ncj) + id_arr(:) = pl%id(idx_arr(:)) + end associate + end do + + ! Consolidate the groups of collsional parents with any children they may have into a single "family" index array + fam_size = 2 + sum(nchild(:)) + allocate(family(fam_size)) + family = [parent_child_index_array(1)%idx(:),parent_child_index_array(2)%idx(:)] + fam_size = count(pl%status(family(:)) == ACTIVE) + family = pack(family(:), pl%status(family(:)) == ACTIVE) + + ! Find the barycenter of each body along with its children, if it has any + do j = 1, 2 + x(:, j) = pl%xb(:, idx_parent(j)) + v(:, j) = pl%vb(:, idx_parent(j)) + Ip(:, j) = mass(j) * pl%Ip(:, idx_parent(j)) + ! Assume principal axis rotation about axis corresponding to highest moment of inertia (3rd Ip) + L_spin(:, j) = Ip(3, j) * radius(j)**2 * pl%rot(:, idx_parent(j)) + + ! Use conservation of energy and angular momentum to adjust velocities and distances to be those equivalent to where they would be when the mutual radii are touching + !call vector_adjust(mass(j), x(:,j), v(:,j)) + if (nchild(j) > 0) then + do i = 1, nchild(j) ! Loop over all children and take the mass weighted mean of the properties + idx_child = parent_child_index_array(j)%idx(i + 1) + if ((idx_child) /= COLLISION) cycle + mchild = pl%Gmass(idx_child) + xchild(:) = pl%xb(:, idx_child) + vchild(:) = pl%vb(:, idx_child) + volchild = (4.0_DP / 3.0_DP) * PI * pl%radius(idx_child)**3 + volume(j) = volume(j) + volchild + ! Get angular momentum of the child-parent pair and add that to the spin + xcom(:) = (mass(j) * x(:,j) + mchild * xchild(:)) / (mass(j) + mchild) + vcom(:) = (mass(j) * v(:,j) + mchild * vchild(:)) / (mass(j) + mchild) + xc(:) = x(:, j) - xcom(:) + vc(:) = v(:, j) - vcom(:) + xcrossv(:) = xc(:) .cross. vc(:) + L_spin(:, j) = L_spin(:, j) + mass(j) * xcrossv(:) + + xc(:) = xchild(:) - xcom(:) + vc(:) = vchild(:) - vcom(:) + xcrossv(:) = xc(:) .cross. vc(:) + L_spin(:, j) = L_spin(:, j) + mchild * xcrossv(:) + + ! Add the child's spin + L_spin(:, j) = L_spin(:, j) + mchild * pl%Ip(3, idx_child) * pl%radius(idx_child)**2 * pl%rot(:, idx_child) + + ! Merge the child and parent + mass(j) = mass(j) + mchild + x(:, j) = xcom(:) + v(:, j) = vcom(:) + Ip(:, j) = Ip(:, j) + mchild * pl%Ip(:, idx_child) + end do + end if + density(j) = mass(j) / volume(j) + radius(j) = ((3 * mass(j)) / (density(j) * 4 * pi))**(1.0_DP / 3.0_DP) + Ip(:, j) = Ip(:, j) / mass(j) + end do + lflag = .true. + + return + end function symba_collision_consolidate_familes + module subroutine symba_collision_encounter_scrub(self, system, param) !! author: David A. Minton !! From 96e31703c93e57eb282d49d534f60d7b72b37c41 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 14:59:37 -0400 Subject: [PATCH 33/42] Added start of merger resolving code --- src/modules/symba_classes.f90 | 4 +-- src/symba/symba_collision.f90 | 61 ++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 88c973aee..45b5acfbc 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -283,7 +283,7 @@ end subroutine symba_io_dump_particle_info module subroutine symba_io_param_reader(self, unit, iotype, v_list, iostat, iomsg) implicit none - class(symba_parameters), intent(inout) :: self !! Collection of SyMBA parameters + class(symba_parameters), intent(inout) :: self !! Current run configuration parameters with SyMBA additionss integer, intent(in) :: unit !! File unit number character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT. !! If you do not include a char-literal-constant, the iotype argument contains only DT. @@ -294,7 +294,7 @@ end subroutine symba_io_param_reader module subroutine symba_io_param_writer(self, unit, iotype, v_list, iostat, iomsg) implicit none - class(symba_parameters),intent(in) :: self !! Collection of SyMBA parameters + class(symba_parameters),intent(in) :: self !! Current run configuration parameters with SyMBA additions integer, intent(in) :: unit !! File unit number character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT. !! If you do not include a char-literal-constant, the iotype argument contains only DT. diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 13c874b0f..edb02dee5 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -143,7 +143,7 @@ pure elemental function symba_collision_check_one(xr, yr, zr, vxr, vyr, vzr, Gmt end function symba_collision_check_one - function symba_collision_consolidate_familes(pl, idx_parent, family, x, v, mass, radius, L_spin, Ip) result(lflag) + function symba_collision_consolidate_familes(pl, param, idx_parent, family, x, v, mass, radius, L_spin, Ip) result(lflag) !! author: David A. Minton !! !! Loops through the pl-pl collision list and groups families together by index. Outputs the indices of all family members, @@ -151,6 +151,7 @@ function symba_collision_consolidate_familes(pl, idx_parent, family, x, v, mass, implicit none ! Arguments class(symba_pl), intent(inout) :: pl !! SyMBA massive body object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions integer(I4B), dimension(2), intent(inout) :: idx_parent !! Index of the two bodies considered the "parents" of the collision integer(I4B), dimension(:), allocatable, intent(out) :: family !! List of indices of all bodies inovlved in the collision real(DP), dimension(NDIM,2), intent(out) :: x, v, L_spin, Ip !! Output values that represent a 2-body equivalent of a possibly 2+ body collision @@ -209,6 +210,8 @@ function symba_collision_consolidate_familes(pl, idx_parent, family, x, v, mass, family = [parent_child_index_array(1)%idx(:),parent_child_index_array(2)%idx(:)] fam_size = count(pl%status(family(:)) == ACTIVE) family = pack(family(:), pl%status(family(:)) == ACTIVE) + L_spin(:,:) = 0.0_DP + Ip(:,:) = 0.0_DP ! Find the barycenter of each body along with its children, if it has any do j = 1, 2 @@ -216,10 +219,8 @@ function symba_collision_consolidate_familes(pl, idx_parent, family, x, v, mass, v(:, j) = pl%vb(:, idx_parent(j)) Ip(:, j) = mass(j) * pl%Ip(:, idx_parent(j)) ! Assume principal axis rotation about axis corresponding to highest moment of inertia (3rd Ip) - L_spin(:, j) = Ip(3, j) * radius(j)**2 * pl%rot(:, idx_parent(j)) + if (param%lrotation) L_spin(:, j) = Ip(3, j) * radius(j)**2 * pl%rot(:, idx_parent(j)) - ! Use conservation of energy and angular momentum to adjust velocities and distances to be those equivalent to where they would be when the mutual radii are touching - !call vector_adjust(mass(j), x(:,j), v(:,j)) if (nchild(j) > 0) then do i = 1, nchild(j) ! Loop over all children and take the mass weighted mean of the properties idx_child = parent_child_index_array(j)%idx(i + 1) @@ -230,31 +231,33 @@ function symba_collision_consolidate_familes(pl, idx_parent, family, x, v, mass, volchild = (4.0_DP / 3.0_DP) * PI * pl%radius(idx_child)**3 volume(j) = volume(j) + volchild ! Get angular momentum of the child-parent pair and add that to the spin - xcom(:) = (mass(j) * x(:,j) + mchild * xchild(:)) / (mass(j) + mchild) - vcom(:) = (mass(j) * v(:,j) + mchild * vchild(:)) / (mass(j) + mchild) - xc(:) = x(:, j) - xcom(:) - vc(:) = v(:, j) - vcom(:) - xcrossv(:) = xc(:) .cross. vc(:) - L_spin(:, j) = L_spin(:, j) + mass(j) * xcrossv(:) - - xc(:) = xchild(:) - xcom(:) - vc(:) = vchild(:) - vcom(:) - xcrossv(:) = xc(:) .cross. vc(:) - L_spin(:, j) = L_spin(:, j) + mchild * xcrossv(:) - ! Add the child's spin - L_spin(:, j) = L_spin(:, j) + mchild * pl%Ip(3, idx_child) * pl%radius(idx_child)**2 * pl%rot(:, idx_child) + if (param%lrotation) then + xcom(:) = (mass(j) * x(:,j) + mchild * xchild(:)) / (mass(j) + mchild) + vcom(:) = (mass(j) * v(:,j) + mchild * vchild(:)) / (mass(j) + mchild) + xc(:) = x(:, j) - xcom(:) + vc(:) = v(:, j) - vcom(:) + xcrossv(:) = xc(:) .cross. vc(:) + L_spin(:, j) = L_spin(:, j) + mass(j) * xcrossv(:) + + xc(:) = xchild(:) - xcom(:) + vc(:) = vchild(:) - vcom(:) + xcrossv(:) = xc(:) .cross. vc(:) + L_spin(:, j) = L_spin(:, j) + mchild * xcrossv(:) + + L_spin(:, j) = L_spin(:, j) + mchild * pl%Ip(3, idx_child) * pl%radius(idx_child)**2 * pl%rot(:, idx_child) + Ip(:, j) = Ip(:, j) + mchild * pl%Ip(:, idx_child) + end if ! Merge the child and parent mass(j) = mass(j) + mchild x(:, j) = xcom(:) v(:, j) = vcom(:) - Ip(:, j) = Ip(:, j) + mchild * pl%Ip(:, idx_child) end do end if density(j) = mass(j) / volume(j) radius(j) = ((3 * mass(j)) / (density(j) * 4 * pi))**(1.0_DP / 3.0_DP) - Ip(:, j) = Ip(:, j) / mass(j) + if (param%lrotation) Ip(:, j) = Ip(:, j) / mass(j) end do lflag = .true. @@ -418,6 +421,26 @@ module subroutine symba_collision_resolve_mergers(self, system, param) class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions ! Internals + integer(I4B) :: i + logical :: lgoodcollision + integer(I4B), dimension(:), allocatable :: family !! List of indices of all bodies inovlved in the collision + integer(I4B), dimension(2) :: idx_parent !! Index of the two bodies considered the "parents" of the collision + real(DP), dimension(NDIM,2) :: x, v, L_spin, Ip !! Output values that represent a 2-body equivalent of a possibly 2+ body collision + real(DP), dimension(2) :: mass, radius !! Output values that represent a 2-body equivalent of a possibly 2+ body collision + + associate(plpl_collisions => self, ncollisions => self%nenc, idx1 => self%index1, idx2 => self%index2) + select type(pl => system%pl) + class is (symba_pl) + do i = 1, ncollisions + idx_parent(1) = pl%kin(idx1(i))%parent + idx_parent(2) = pl%kin(idx2(i))%parent + lgoodcollision = symba_collision_consolidate_familes(pl, param, idx_parent, family, x, v, mass, radius, L_spin, Ip) + if (.not. lgoodcollision) cycle + if (any(pl%status(idx_parent(:)) /= COLLISION)) cycle ! One of these two bodies has already been resolved + !call symba_collision_casemerge(system, param, family, x, v, mass, radius, L_spin, Ip) + end do + end select + end associate return end subroutine symba_collision_resolve_mergers From 8ea46e177060fd3a73cdad57c0b15ea3b1147e5a Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 15:19:36 -0400 Subject: [PATCH 34/42] Fixed some issues with masks in the encounter to collision scrub --- src/symba/symba_collision.f90 | 84 ++++++++++++++++++----------------- src/symba/symba_discard.f90 | 2 + src/util/util_spill.f90 | 9 ++-- 3 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index edb02dee5..efae0ba39 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -217,9 +217,11 @@ function symba_collision_consolidate_familes(pl, param, idx_parent, family, x, v do j = 1, 2 x(:, j) = pl%xb(:, idx_parent(j)) v(:, j) = pl%vb(:, idx_parent(j)) - Ip(:, j) = mass(j) * pl%Ip(:, idx_parent(j)) ! Assume principal axis rotation about axis corresponding to highest moment of inertia (3rd Ip) - if (param%lrotation) L_spin(:, j) = Ip(3, j) * radius(j)**2 * pl%rot(:, idx_parent(j)) + if (param%lrotation) then + Ip(:, j) = mass(j) * pl%Ip(:, idx_parent(j)) + L_spin(:, j) = Ip(3, j) * radius(j)**2 * pl%rot(:, idx_parent(j)) + end if if (nchild(j) > 0) then do i = 1, nchild(j) ! Loop over all children and take the mass weighted mean of the properties @@ -282,49 +284,49 @@ module subroutine symba_collision_encounter_scrub(self, system, param) integer(I4B) :: i, index_coll, ncollisions, nunique_parent type(symba_plplenc) :: plplenc_noncollision - select type (pl => system%pl) class is (symba_pl) associate(plplenc_list => self, nplplenc => self%nenc, idx1 => self%index1, idx2 => self%index2, plparent => pl%kin%parent) lplpl_collision(:) = plplenc_list%status(1:nplplenc) == COLLISION - if (.not.any(lplpl_collision)) return - - ! Get the subset of pl-pl encounters that lead to a collision - ncollisions = count(lplpl_collision(:)) - allocate(collision_idx(ncollisions)) - collision_idx = pack([(i, i=1, nplplenc)], lplpl_collision) - - ! Get the subset of collisions that involve a unique pair of parents - allocate(lplpl_unique_parent(ncollisions)) - - lplpl_unique_parent(:) = plparent(idx1(collision_idx(:))) /= plparent(idx2(collision_idx(:))) - nunique_parent = count(lplpl_unique_parent(:)) - allocate(unique_parent_idx(nunique_parent)) - unique_parent_idx = pack(collision_idx(:), lplpl_unique_parent(:)) - - ! Scrub all pl-pl collisions involving unique pairs of parents, which will remove all duplicates and leave behind - ! all pairs that have themselves as parents but are not part of the unique parent list. This can hapepn in rare cases - ! due to restructuring of parent/child relationships when there are large numbers of multi-body collisions in a single - ! step - lplpl_unique_parent(:) = .true. - do index_coll = 1, ncollisions - associate(ip1 => plparent(idx1(collision_idx(index_coll))), ip2 => plparent(idx2(collision_idx(index_coll)))) - lplpl_unique_parent(:) = .not. ( any(plparent(idx1(unique_parent_idx(:))) == ip1) .or. & - any(plparent(idx2(unique_parent_idx(:))) == ip1) .or. & - any(plparent(idx1(unique_parent_idx(:))) == ip2) .or. & - any(plparent(idx2(unique_parent_idx(:))) == ip2) ) - end associate - end do - - ! Reassemble collision index list to include only those containing the unique pairs of parents, plus all the non-unique pairs that don't - ! contain a parent body on the unique parent list. - ncollisions = nunique_parent + count(lplpl_unique_parent) - collision_idx = [unique_parent_idx(:), pack(collision_idx(:), lplpl_unique_parent(:))] - - ! Create a mask that contains only the pl-pl encounters that did not result in a collision, and then discard them - lplpl_collision(:) = .true. - lplpl_collision(collision_idx(:)) = .false. - call plplenc_list%spill(plplenc_noncollision, lplpl_collision, ldestructive = .true.) + if (any(lplpl_collision)) then ! Collisions have been detected in this step. So we need to determine which of them are between unique bodies. + + ! Get the subset of pl-pl encounters that lead to a collision + ncollisions = count(lplpl_collision(:)) + allocate(collision_idx(ncollisions)) + collision_idx = pack([(i, i=1, nplplenc)], lplpl_collision) + + ! Get the subset of collisions that involve a unique pair of parents + allocate(lplpl_unique_parent(ncollisions)) + + lplpl_unique_parent(:) = plparent(idx1(collision_idx(:))) /= plparent(idx2(collision_idx(:))) + nunique_parent = count(lplpl_unique_parent(:)) + allocate(unique_parent_idx(nunique_parent)) + unique_parent_idx = pack(collision_idx(:), lplpl_unique_parent(:)) + + ! Scrub all pl-pl collisions involving unique pairs of parents, which will remove all duplicates and leave behind + ! all pairs that have themselves as parents but are not part of the unique parent list. This can hapepn in rare cases + ! due to restructuring of parent/child relationships when there are large numbers of multi-body collisions in a single + ! step + lplpl_unique_parent(:) = .true. + do index_coll = 1, ncollisions + associate(ip1 => plparent(idx1(collision_idx(index_coll))), ip2 => plparent(idx2(collision_idx(index_coll)))) + lplpl_unique_parent(:) = .not. ( any(plparent(idx1(unique_parent_idx(:))) == ip1) .or. & + any(plparent(idx2(unique_parent_idx(:))) == ip1) .or. & + any(plparent(idx1(unique_parent_idx(:))) == ip2) .or. & + any(plparent(idx2(unique_parent_idx(:))) == ip2) ) + end associate + end do + + ! Reassemble collision index list to include only those containing the unique pairs of parents, plus all the non-unique pairs that don't + ! contain a parent body on the unique parent list. + ncollisions = nunique_parent + count(lplpl_unique_parent) + collision_idx = [unique_parent_idx(:), pack(collision_idx(:), lplpl_unique_parent(:))] + + ! Create a mask that contains only the pl-pl encounters that did not result in a collision, and then discard them + lplpl_collision(:) = .false. + lplpl_collision(collision_idx(:)) = .true. + end if + call plplenc_list%spill(plplenc_noncollision, .not.lplpl_collision, ldestructive=.true.) ! Remove any encounters that are not collisions from the list. end associate end select diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 57b26e8ea..2fa789d46 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -152,6 +152,8 @@ module subroutine symba_discard_pl(self, system, param) associate(pl => self, plplenc_list => system%plplenc_list) call symba_discard_nonplpl(self, system, param) call plplenc_list%scrub_non_collision(system, param) + if (plplenc_list%nenc == 0) return ! No collisions to resolve + call pl%h2b(system%cb) if (param%lfragmentation) then call plplenc_list%resolve_fragmentations(system, param) diff --git a/src/util/util_spill.f90 b/src/util/util_spill.f90 index fc945765c..0cef49194 100644 --- a/src/util/util_spill.f90 +++ b/src/util/util_spill.f90 @@ -183,12 +183,8 @@ module subroutine util_spill_body(self, discards, lspill_list, ldestructive) ! Therefore we need to set the nbody values for both the keeps and discareds discards%nbody = count(lspill_list(:)) keeps%nbody = count(.not.lspill_list(:)) - if (allocated(keeps%ldiscard)) deallocate(keeps%ldiscard) - if (allocated(discards%ldiscard)) deallocate(discards%ldiscard) - allocate(keeps%ldiscard(keeps%nbody)) - allocate(discards%ldiscard(discards%nbody)) - keeps%ldiscard = .false. - discards%ldiscard = .true. + if (keeps%nbody > size(keeps%status)) keeps%status(keeps%nbody+1:size(keeps%status)) = INACTIVE + end associate return @@ -222,6 +218,7 @@ module subroutine util_spill_encounter(self, discards, lspill_list, ldestructive ! Therefore we need to set the nenc values for both the keeps and discareds discards%nenc = count(lspill_list(:)) keeps%nenc = count(.not.lspill_list(:)) + if (keeps%nenc > size(keeps%status)) keeps%status(keeps%nenc+1:size(keeps%status)) = INACTIVE end associate return From cf2feb1ff886d238a476074c11bd27567591f35a Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 16:56:41 -0400 Subject: [PATCH 35/42] Added merger code --- src/modules/rmvs_classes.f90 | 4 +- src/modules/symba_classes.f90 | 74 +++++++++++----- src/modules/whm_classes.f90 | 2 +- src/setup/setup.f90 | 4 +- src/symba/symba_collision.f90 | 18 ++-- src/symba/symba_discard.f90 | 1 + src/symba/symba_fragmentation.f90 | 135 ++++++++++++++++++++++++++++++ src/symba/symba_io.f90 | 54 ++++++------ src/symba/symba_setup.f90 | 26 ++++++ src/symba/symba_util.f90 | 50 ++++++++++- 10 files changed, 307 insertions(+), 61 deletions(-) create mode 100644 src/symba/symba_fragmentation.f90 diff --git a/src/modules/rmvs_classes.f90 b/src/modules/rmvs_classes.f90 index 315b098a8..fbbfa15fe 100644 --- a/src/modules/rmvs_classes.f90 +++ b/src/modules/rmvs_classes.f90 @@ -70,7 +70,7 @@ module rmvs_classes procedure :: encounter_check => rmvs_encounter_check_tp !! Checks if any test particles are undergoing a close encounter with a massive body procedure :: accel => rmvs_kick_getacch_tp !! Calculates either the standard or modified version of the acceleration depending if the !! if the test particle is undergoing a close encounter or not - procedure :: setup => rmvs_setup_tp !! Constructor method - Allocates space for number of particles + procedure :: setup => rmvs_setup_tp !! Constructor method - Allocates space for the input number of bodiess procedure :: append => rmvs_util_append_tp !! Appends elements from one structure to another procedure :: fill => rmvs_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => rmvs_util_resize_tp !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. @@ -93,7 +93,7 @@ module rmvs_classes class(rmvs_nbody_system), dimension(:), allocatable :: planetocentric !! Planetocentric version of the massive body objects (one for each massive body) logical :: lplanetocentric = .false. !! Flag that indicates that the object is a planetocentric set of masive bodies used for close encounter calculations contains - procedure :: setup => rmvs_setup_pl !! Constructor method - Allocates space for number of particles + procedure :: setup => rmvs_setup_pl !! Constructor method - Allocates space for the input number of bodiess procedure :: append => rmvs_util_append_pl !! Appends elements from one structure to another procedure :: fill => rmvs_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => rmvs_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 45b5acfbc..b0daf9496 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -91,16 +91,24 @@ module symba_classes procedure :: drift => symba_drift_pl !! Method for Danby drift in Democratic Heliocentric coordinates. Sets the mask to the current recursion level procedure :: encounter_check => symba_encounter_check_pl !! Checks if massive bodies are going through close encounters with each other procedure :: accel => symba_kick_getacch_pl !! Compute heliocentric accelerations of massive bodies - procedure :: setup => symba_setup_pl !! Constructor method - Allocates space for number of particle + procedure :: setup => symba_setup_pl !! Constructor method - Allocates space for the input number of bodies procedure :: append => symba_util_append_pl !! Appends elements from one structure to another procedure :: fill => symba_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: get_peri => symba_util_peri_pl !! Determine system pericenter passages for massive bodies - procedure :: resize => symba_util_resize_pl !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. + procedure :: resize => symba_util_resize_pl !! Checks the current size of a SyMBA massive body against the requested size and resizes it if it is too small. procedure :: sort => symba_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods procedure :: spill => symba_util_spill_pl !! "Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) end type symba_pl + type, extends(symba_pl) :: symba_merger + integer(I4B), dimension(:), allocatable :: ncomp + contains + procedure :: append => symba_util_append_merger !! Appends elements from one structure to another + procedure :: resize => symba_util_resize_merger !! Checks the current size of a SyMBA merger list against the requested size and resizes it if it is too small. + procedure :: setup => symba_setup_merger !! Constructor method - Allocates space for the input number of bodies + end type symba_merger + !******************************************************************************************************************************** ! symba_tp class definitions and method interfaces !******************************************************************************************************************************* @@ -113,7 +121,7 @@ module symba_classes procedure :: drift => symba_drift_tp !! Method for Danby drift in Democratic Heliocentric coordinates. Sets the mask to the current recursion level procedure :: encounter_check => symba_encounter_check_tp !! Checks if any test particles are undergoing a close encounter with a massive body procedure :: accel => symba_kick_getacch_tp !! Compute heliocentric accelerations of test particles - procedure :: setup => symba_setup_tp !! Constructor method - Allocates space for number of particle + procedure :: setup => symba_setup_tp !! Constructor method - Allocates space for the input number of bodies procedure :: append => symba_util_append_tp !! Appends elements from one structure to another procedure :: fill => symba_util_fill_tp !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: resize => symba_util_resize_tp !! Checks the current size of a Swiftest body against the requested size and resizes it if it is too small. @@ -151,8 +159,8 @@ module symba_classes ! symba_nbody_system class definitions and method interfaces !******************************************************************************************************************************** type, extends(helio_nbody_system) :: symba_nbody_system - class(symba_pl), allocatable :: mergeadd_list !! List of added bodies in mergers or collisions - class(symba_pl), allocatable :: mergesub_list !! List of subtracted bodies in mergers or collisions + class(symba_merger), allocatable :: mergeadd_list !! List of added bodies in mergers or collisions + class(symba_merger), allocatable :: mergesub_list !! List of subtracted bodies in mergers or collisions class(symba_pltpenc), allocatable :: pltpenc_list !! List of massive body-test particle encounters in a single step class(symba_plplenc), allocatable :: plplenc_list !! List of massive body-massive body encounters in a single step integer(I4B) :: irec !! System recursion level @@ -266,6 +274,16 @@ module function symba_encounter_check_tp(self, system, dt, irec) result(lany_enc logical :: lany_encounter !! Returns true if there is at least one close encounter end function symba_encounter_check_tp + module function symba_fragmentation_casemerge(system, param, family, x, v, mass, radius, L_spin, Ip) result(status) + implicit none + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions + integer(I4B), dimension(:), intent(in) :: family !! List of indices of all bodies inovlved in the collision + real(DP), dimension(:,:), intent(in) :: x, v, L_spin, Ip !! Input values that represent a 2-body equivalent of a possibly 2+ body collision + real(DP), dimension(:), intent(in) :: mass, radius !! Input values that represent a 2-body equivalent of a possibly 2+ body collisio + integer(I4B) :: status !! Status flag assigned to this outcome + end function symba_fragmentation_casemerge + module subroutine symba_io_write_discard(self, param) use swiftest_classes, only : swiftest_parameters implicit none @@ -357,11 +375,26 @@ module subroutine symba_io_write_frame_info(self, iu, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters end subroutine symba_io_write_frame_info + module subroutine symba_setup_initialize_system(self, param) + use swiftest_classes, only : swiftest_parameters + implicit none + class(symba_nbody_system), intent(inout) :: self !! SyMBA system object + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters + end subroutine symba_setup_initialize_system + + module subroutine symba_setup_merger(self, n, param) + use swiftest_classes, only : swiftest_parameters + implicit none + class(symba_merger), intent(inout) :: self !! SyMBA merger list 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 symba_setup_merger + module subroutine symba_setup_pl(self, n, param) use swiftest_classes, only : swiftest_parameters implicit none - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - integer(I4B), intent(in) :: n !! Number of particles to allocate space for + 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 parameters end subroutine symba_setup_pl @@ -371,19 +404,6 @@ module subroutine symba_setup_pltpenc(self,n) integer(I4B), intent(in) :: n !! Number of encounters to allocate space for end subroutine symba_setup_pltpenc - module subroutine symba_setup_plplenc(self,n) - implicit none - class(symba_plplenc), intent(inout) :: self !! SyMBA pl-tp encounter structure - integer(I4B), intent(in) :: n !! Number of encounters to allocate space for - end subroutine symba_setup_plplenc - - module subroutine symba_setup_initialize_system(self, param) - use swiftest_classes, only : swiftest_parameters - implicit none - class(symba_nbody_system), intent(inout) :: self !! SyMBA system object - class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters - end subroutine symba_setup_initialize_system - module subroutine symba_setup_tp(self, n, param) use swiftest_classes, only : swiftest_parameters implicit none @@ -448,6 +468,14 @@ end subroutine symba_util_append_arr_kin end interface interface + module subroutine symba_util_append_merger(self, source, lsource_mask) + use swiftest_classes, only : swiftest_body + implicit none + class(symba_merger), intent(inout) :: self !! SyMBA massive body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + end subroutine symba_util_append_merger + module subroutine symba_util_append_pl(self, source, lsource_mask) use swiftest_classes, only : swiftest_body implicit none @@ -522,6 +550,12 @@ end subroutine symba_util_resize_arr_kin end interface interface + module subroutine symba_util_resize_merger(self, nnew) + implicit none + class(symba_merger), intent(inout) :: self !! SyMBA merger list object + integer(I4B), intent(in) :: nnew !! New size neded + end subroutine symba_util_resize_merger + module subroutine symba_util_resize_pl(self, nnew) implicit none class(symba_pl), intent(inout) :: self !! SyMBA massive body object diff --git a/src/modules/whm_classes.f90 b/src/modules/whm_classes.f90 index e581e52b1..a79f52bca 100644 --- a/src/modules/whm_classes.f90 +++ b/src/modules/whm_classes.f90 @@ -46,7 +46,7 @@ module whm_classes procedure :: sort => whm_util_sort_pl !! Sort a WHM massive body object in-place. procedure :: rearrange => whm_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods procedure :: spill => whm_util_spill_pl !!"Spills" bodies from one object to another depending on the results of a mask (uses the PACK intrinsic) - procedure :: setup => whm_setup_pl !! Constructor method - Allocates space for number of particles + procedure :: setup => whm_setup_pl !! Constructor method - Allocates space for the input number of bodiess procedure :: step => whm_step_pl !! Steps the body forward one stepsize end type whm_pl diff --git a/src/setup/setup.f90 b/src/setup/setup.f90 index ca5f38c6e..edb641907 100644 --- a/src/setup/setup.f90 +++ b/src/setup/setup.f90 @@ -54,8 +54,8 @@ module subroutine setup_construct_system(system, param) allocate(symba_pl :: system%pl) allocate(symba_tp :: system%tp) allocate(symba_tp :: system%tp_discards) - allocate(symba_pl :: system%mergeadd_list) - allocate(symba_pl :: system%mergesub_list) + allocate(symba_merger :: system%mergeadd_list) + allocate(symba_merger :: system%mergesub_list) allocate(symba_plplenc :: system%plplenc_list) allocate(symba_pltpenc :: system%pltpenc_list) end select diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index efae0ba39..0f8b4d519 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -208,8 +208,8 @@ function symba_collision_consolidate_familes(pl, param, idx_parent, family, x, v fam_size = 2 + sum(nchild(:)) allocate(family(fam_size)) family = [parent_child_index_array(1)%idx(:),parent_child_index_array(2)%idx(:)] - fam_size = count(pl%status(family(:)) == ACTIVE) - family = pack(family(:), pl%status(family(:)) == ACTIVE) + fam_size = count(pl%status(family(:)) == COLLISION) + family = pack(family(:), pl%status(family(:)) == COLLISION) L_spin(:,:) = 0.0_DP Ip(:,:) = 0.0_DP @@ -423,12 +423,12 @@ module subroutine symba_collision_resolve_mergers(self, system, param) class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions ! Internals - integer(I4B) :: i - logical :: lgoodcollision - integer(I4B), dimension(:), allocatable :: family !! List of indices of all bodies inovlved in the collision - integer(I4B), dimension(2) :: idx_parent !! Index of the two bodies considered the "parents" of the collision - real(DP), dimension(NDIM,2) :: x, v, L_spin, Ip !! Output values that represent a 2-body equivalent of a possibly 2+ body collision - real(DP), dimension(2) :: mass, radius !! Output values that represent a 2-body equivalent of a possibly 2+ body collision + integer(I4B), dimension(:), allocatable :: family !! List of indices of all bodies inovlved in the collision + integer(I4B), dimension(2) :: idx_parent !! Index of the two bodies considered the "parents" of the collision + real(DP), dimension(NDIM,2) :: x, v, L_spin, Ip !! Output values that represent a 2-body equivalent of a possibly 2+ body collision + real(DP), dimension(2) :: mass, radius !! Output values that represent a 2-body equivalent of a possibly 2+ body collision + logical :: lgoodcollision + integer(I4B) :: i, status associate(plpl_collisions => self, ncollisions => self%nenc, idx1 => self%index1, idx2 => self%index2) select type(pl => system%pl) @@ -439,7 +439,7 @@ module subroutine symba_collision_resolve_mergers(self, system, param) lgoodcollision = symba_collision_consolidate_familes(pl, param, idx_parent, family, x, v, mass, radius, L_spin, Ip) if (.not. lgoodcollision) cycle if (any(pl%status(idx_parent(:)) /= COLLISION)) cycle ! One of these two bodies has already been resolved - !call symba_collision_casemerge(system, param, family, x, v, mass, radius, L_spin, Ip) + status = symba_fragmentation_casemerge(system, param, family, x, v, mass, radius, L_spin, Ip) end do end select end associate diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 2fa789d46..1c5b4a732 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -153,6 +153,7 @@ module subroutine symba_discard_pl(self, system, param) call symba_discard_nonplpl(self, system, param) call plplenc_list%scrub_non_collision(system, param) if (plplenc_list%nenc == 0) return ! No collisions to resolve + write(*, *) "Collision detected at time t = ",param%t call pl%h2b(system%cb) if (param%lfragmentation) then diff --git a/src/symba/symba_fragmentation.f90 b/src/symba/symba_fragmentation.f90 new file mode 100644 index 000000000..ccc79892f --- /dev/null +++ b/src/symba/symba_fragmentation.f90 @@ -0,0 +1,135 @@ +submodule (symba_classes) s_symba_fragmentation + use swiftest +contains + + module function symba_fragmentation_casemerge(system, param, family, x, v, mass, radius, L_spin, Ip) result(status) + !! author: Jennifer L.L. Pouplin, Carlisle A. Wishard, and David A. Minton + !! + !! Merge planets. + !! + !! Adapted from David E. Kaufmann's Swifter routines symba_merge_pl.f90 and symba_discard_merge_pl.f90 + !! + !! Adapted from Hal Levison's Swift routines symba5_merge.f and discard_mass_merge.f + implicit none + ! Arguments + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions + integer(I4B), dimension(:), intent(in) :: family !! List of indices of all bodies inovlved in the collision + real(DP), dimension(:,:), intent(in) :: x, v, L_spin, Ip !! Input values that represent a 2-body equivalent of a possibly 2+ body collision + real(DP), dimension(:), intent(in) :: mass, radius !! Input values that represent a 2-body equivalent of a possibly 2+ body collision + ! Result + integer(I4B) :: status !! Status flag assigned to this outcome + ! Internals + integer(I4B) :: i, j, ibiggest, nfamily, nstart, nend + real(DP) :: mass_new, radius_new, volume_new, pe + real(DP), dimension(NDIM) :: xcom, vcom, xc, vc, xcrossv + real(DP), dimension(2) :: vol + real(DP), dimension(NDIM) :: L_orb_old, L_spin_old + real(DP), dimension(NDIM) :: L_spin_new, rot_new, Ip_new + logical, dimension(system%pl%nbody) :: lmask + class(symba_pl), allocatable :: plnew + + select type(pl => system%pl) + class is (symba_pl) + associate(mergeadd_list => system%mergeadd_list, mergesub_list => system%mergesub_list, cb => system%cb) + status = MERGED + write(*, '("Merging bodies ",99(I8,",",:))') pl%id(family(:)) + mass_new = sum(mass(:)) + + ! Merged body is created at the barycenter of the original bodies + xcom(:) = (mass(1) * x(:,1) + mass(2) * x(:,2)) / mass_new + vcom(:) = (mass(1) * v(:,1) + mass(2) * v(:,2)) / mass_new + + ! Get mass weighted mean of Ip and + vol(:) = 4._DP / 3._DP * PI * radius(:)**3 + volume_new = sum(vol(:)) + radius_new = (3 * volume_new / (4 * PI))**(1._DP / 3._DP) + + L_orb_old(:) = 0.0_DP + + ! Compute orbital angular momentum of pre-impact system + do i = 1, 2 + xc(:) = x(:, i) - xcom(:) + vc(:) = v(:, i) - vcom(:) + xcrossv(:) = xc(:) .cross. vc(:) + L_orb_old(:) = L_orb_old(:) + mass(i) * xcrossv(:) + end do + + if (param%lrotation) then + Ip_new(:) = (mass(1) * Ip(:,1) + mass(2) * Ip(:,2)) / mass_new + L_spin_old(:) = L_spin(:,1) + L_spin(:,2) + + ! Conserve angular momentum by putting pre-impact orbital momentum into spin of the new body + L_spin_new(:) = L_orb_old(:) + L_spin_old(:) + + ! Assume prinicpal axis rotation on 3rd Ip axis + rot_new(:) = L_spin_new(:) / (Ip_new(3) * mass_new * radius_new**2) + else ! If spin is not enabled, we will consider the lost pre-collision angular momentum as "escaped" and add it to our bookkeeping variable + system%Lescape(:) = system%Lescape(:) + L_orb_old(:) + end if + + ! Keep track of the component of potential energy due to the pre-impact family for book-keeping + nfamily = size(family(:)) + pe = 0.0_DP + do j = 1, nfamily + do i = j + 1, nfamily + pe = pe - pl%Gmass(i) * pl%Gmass(j) / norm2(pl%xb(:, i) - pl%xb(:, j)) + end do + end do + system%Ecollisions = system%Ecollisions + pe + system%Euntracked = system%Euntracked - pe + + ! Add the family bodies to the subtraction list + lmask(:) = .false. + lmask(family(:)) = .true. + pl%status(family(:)) = MERGED + nstart = mergesub_list%nbody + 1 + nend = mergesub_list%nbody + nfamily + call mergesub_list%append(pl, lmask) + ! Record how many bodies were subtracted in this event + mergesub_list%ncomp(nstart:nend) = nfamily + + ! Create the new merged body + allocate(plnew, mold=pl) + call plnew%setup(1, param) + + ! The merged body's name will be that of the largest of the two parents + ibiggest = maxloc(pl%Gmass(family(:)), dim=1) + plnew%id(1) = pl%id(family(ibiggest)) + plnew%status(1) = ACTIVE + plnew%xb(:,1) = xcom(:) + plnew%vb(:,1) = vcom(:) + plnew%xh(:,1) = xcom(:) - cb%xb(:) + plnew%vh(:,1) = vcom(:) - cb%vb(:) + plnew%mass(1) = mass_new + plnew%Gmass(1) = param%GU * mass_new + plnew%density(1) = mass_new / volume_new + plnew%radius(1) = radius_new + plnew%info(1) = pl%info(family(ibiggest)) + if (param%lrotation) then + pl%Ip(:,1) = Ip_new(:) + pl%rot(:,1) = rot_new(:) + end if + if (param%ltides) then + plnew%Q = pl%Q(ibiggest) + plnew%k2 = pl%k2(ibiggest) + plnew%tlag = pl%tlag(ibiggest) + end if + + ! Append the new merged body to the list and record how many we made + nstart = mergeadd_list%nbody + 1 + nend = mergeadd_list%nbody + plnew%nbody + call mergeadd_list%append(plnew) + mergeadd_list%ncomp(nstart:nend) = plnew%nbody + + call plnew%setup(0, param) + deallocate(plnew) + + end associate + end select + + return + + end function symba_fragmentation_casemerge + +end submodule s_symba_fragmentation diff --git a/src/symba/symba_io.f90 b/src/symba/symba_io.f90 index f35e45408..d3091155d 100644 --- a/src/symba/symba_io.f90 +++ b/src/symba/symba_io.f90 @@ -215,7 +215,7 @@ module subroutine symba_io_write_discard(self, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters ! Internals integer(I4B), parameter :: LUN = 40 - integer(I4B) :: i, ierr + integer(I4B) :: iadd, isub, j, ierr, nsub, nadd logical, save :: lfirst = .true. real(DP), dimension(:,:), allocatable :: vh character(*), parameter :: HDRFMT = '(E23.16, 1X, I8, 1X, L1)' @@ -245,33 +245,35 @@ module subroutine symba_io_write_discard(self, param) end if write(LUN, HDRFMT) param%t, mergesub_list%nbody, param%lbig_discard - do i = 1, mergesub_list%nbody - write(LUN, NAMEFMT) SUB, mergesub_list%id(i), mergesub_list%status(i) - write(LUN, VECFMT) mergesub_list%xh(1, i), mergesub_list%xh(2, i), mergesub_list%xh(3, i) - write(LUN, VECFMT) mergesub_list%vh(1, i), mergesub_list%vh(2, i), mergesub_list%vh(3, i) + iadd = 1 + isub = 1 + do while (iadd <= mergeadd_list%nbody) + nadd = mergeadd_list%ncomp(iadd) + nsub = mergesub_list%ncomp(isub) + do j = 1, nadd + if (iadd <= mergeadd_list%nbody) then + write(LUN, NAMEFMT) SUB, mergesub_list%id(iadd), mergesub_list%status(iadd) + write(LUN, VECFMT) mergeadd_list%xh(1, iadd), mergeadd_list%xh(2, iadd), mergeadd_list%xh(3, iadd) + write(LUN, VECFMT) mergeadd_list%vh(1, iadd), mergeadd_list%vh(2, iadd), mergeadd_list%vh(3, iadd) + else + exit + end if + iadd = iadd + 1 + end do + do j = 1, nsub + if (isub <= mergesub_list%nbody) then + write(LUN, NAMEFMT) SUB, mergesub_list%id(isub), mergesub_list%status(isub) + write(LUN, VECFMT) mergesub_list%xh(1, isub), mergesub_list%xh(2, isub), mergesub_list%xh(3, isub) + write(LUN, VECFMT) mergesub_list%vh(1, isub), mergesub_list%vh(2, isub), mergesub_list%vh(3, isub) + else + exit + end if + isub = isub + 1 + end do end do - ! This is incomplete until the mergeadd_list methods are completed - ! if (param%lbig_discard) then - ! if (param%lgr) then - ! allocate(pltemp, source = pl) - ! call pltemp%pv2v(param) - ! allocate(vh, source = pltemp%vh) - ! deallocate(pltemp) - ! else - ! allocate(vh, source = pl%vh) - ! end if - - ! write(LUN, NPLFMT) npl - ! do i = 1, npl - ! write(LUN, PLNAMEFMT) pl%id(i), pl%Gmass(i), pl%radius(i) - ! write(LUN, VECFMT) pl%xh(1, i), pl%xh(2, i), pl%xh(3, i) - ! write(LUN, VECFMT) vh(1, i), vh(2, i), vh(3, i) - ! end do - ! deallocate(vh) - ! end if - close(LUN) - end associate + close(LUN) + end associate return end subroutine symba_io_write_discard diff --git a/src/symba/symba_setup.f90 b/src/symba/symba_setup.f90 index 524420609..021873a70 100644 --- a/src/symba/symba_setup.f90 +++ b/src/symba/symba_setup.f90 @@ -35,6 +35,32 @@ module subroutine symba_setup_initialize_system(self, param) end subroutine symba_setup_initialize_system + module subroutine symba_setup_merger(self, n, param) + !! author: David A. Minton + !! + !! Allocate SyMBA test particle structure + !! + !! Equivalent in functionality to David E. Kaufmann's Swifter routine symba_setup.f90 + implicit none + ! Arguments + class(symba_merger), intent(inout) :: self !! SyMBA merger list object + integer(I4B), intent(in) :: n !! Number of particles to allocate space for + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameter + ! Internals + integer(I4B) :: i + + !> Call allocation method for parent class. In this case, helio_pl does not have its own setup method so we use the base method for swiftest_pl + call symba_setup_pl(self, n, param) + if (n <= 0) return + + if (allocated(self%ncomp)) deallocate(self%ncomp) + allocate(self%ncomp(n)) + self%ncomp(:) = 0 + + return + end subroutine symba_setup_merger + + module subroutine symba_setup_pl(self, n, param) !! author: David A. Minton !! diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 56eaacc2c..7063e0910 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -116,6 +116,37 @@ module subroutine symba_util_append_pl(self, source, lsource_mask) end subroutine symba_util_append_pl + module subroutine symba_util_append_merger(self, source, lsource_mask) + !! author: David A. Minton + !! + !! Append components from one massive body object to another. + !! This method will automatically resize the destination body if it is too small + implicit none + ! Arguments + class(symba_merger), intent(inout) :: self !! SyMBA massive body object + class(swiftest_body), intent(in) :: source !! Source object to append + logical, dimension(:), optional, intent(in) :: lsource_mask !! Logical mask indicating which elements to append to + ! Internals + integer(I4B), dimension(:), allocatable :: ncomp_tmp !! Temporary placeholder for ncomp incase we are appending a symba_pl object to a symba_merger + + select type(source) + class is (symba_merger) + call symba_util_append_pl(self, source, lsource_mask) + call util_append(self%ncomp, source%ncomp, lsource_mask) + class is (symba_pl) + call symba_util_append_pl(self, source, lsource_mask) + allocate(ncomp_tmp, mold=source%id) + ncomp_tmp(:) = 0 + call util_append(self%ncomp, ncomp_tmp, lsource_mask) + class default + write(*,*) "Invalid object passed to the append method. Source must be of class symba_pl or its descendents!" + call util_exit(FAILURE) + end select + + return + end subroutine symba_util_append_merger + + module subroutine symba_util_append_tp(self, source, lsource_mask) !! author: David A. Minton !! @@ -406,10 +437,27 @@ module subroutine symba_util_resize_arr_kin(arr, nnew) end subroutine symba_util_resize_arr_kin + module subroutine symba_util_resize_merger(self, nnew) + !! author: David A. Minton + !! + !! Checks the current size of a SyMBA merger list against the requested size and resizes it if it is too small. + implicit none + ! Arguments + class(symba_merger), intent(inout) :: self !! SyMBA massive body object + integer(I4B), intent(in) :: nnew !! New size neded + + call symba_util_resize_pl(self, nnew) + + call util_resize(self%ncomp, nnew) + + return + end subroutine symba_util_resize_merger + + module subroutine symba_util_resize_pl(self, nnew) !! author: David A. Minton !! - !! Checks the current size of a massive body object against the requested size and resizes it if it is too small. + !! 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 From 31b7c695aa1f2a36e596992fa9a8c92fac941f5e Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 17:13:40 -0400 Subject: [PATCH 36/42] Fixed problem with 1pl_1pl initial conditions generator dtypes for ids --- .../1pl_1pl_encounter/init_cond.py | 3 +- .../1pl_1pl_encounter/pl.swiftest.in | Bin 256 -> 248 bytes src/io/io.f90 | 40 +++++++++--------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/init_cond.py b/examples/symba_swifter_comparison/1pl_1pl_encounter/init_cond.py index 20be5a433..ece9101e0 100755 --- a/examples/symba_swifter_comparison/1pl_1pl_encounter/init_cond.py +++ b/examples/symba_swifter_comparison/1pl_1pl_encounter/init_cond.py @@ -131,8 +131,7 @@ plfile = FortranFile(swiftest_pl, 'w') plfile.write_record(npl) - -plfile.write_record(np.array([plid1, plid2])) +plfile.write_record(np.array([plid1, plid2], dtype=np.int32)) plfile.write_record(np.vstack([p_pl1[0],p_pl2[0]])) plfile.write_record(np.vstack([p_pl1[1],p_pl2[1]])) plfile.write_record(np.vstack([p_pl1[2],p_pl2[2]])) diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/pl.swiftest.in b/examples/symba_swifter_comparison/1pl_1pl_encounter/pl.swiftest.in index d8da7a92a44b1e9caa3907ead959cdec31e066cc..1bda0535db1ca1f471c53398b42ba7eb9da4250a 100644 GIT binary patch delta 37 dcmZo*`oSp6!N9=41jHZ!V#D|;AofJn+W self%nbody) - read(iu, iostat=ierr, err=100) self%id(1:n) + read(iu, iostat=ierr, err=100) self%id(:) !read(iu, iostat=ierr, err=100) self%name(1:n) select case (form) case (EL) @@ -849,33 +849,33 @@ module subroutine io_read_frame_body(self, iu, param, form, ierr) if (.not.allocated(self%capom)) allocate(self%capom(n)) if (.not.allocated(self%omega)) allocate(self%omega(n)) if (.not.allocated(self%capm)) allocate(self%capm(n)) - read(iu, iostat=ierr, err=100) self%a(1:n) - read(iu, iostat=ierr, err=100) self%e(1:n) - read(iu, iostat=ierr, err=100) self%inc(1:n) + read(iu, iostat=ierr, err=100) self%a(:) + read(iu, iostat=ierr, err=100) self%e(:) + read(iu, iostat=ierr, err=100) self%inc(:) read(iu, iostat=ierr, err=100) self%capom(:) read(iu, iostat=ierr, err=100) self%omega(:) read(iu, iostat=ierr, err=100) self%capm(:) case (XV) - read(iu, iostat=ierr, err=100) self%xh(1, 1:n) - read(iu, iostat=ierr, err=100) self%xh(2, 1:n) - read(iu, iostat=ierr, err=100) self%xh(3, 1:n) - read(iu, iostat=ierr, err=100) self%vh(1, 1:n) - read(iu, iostat=ierr, err=100) self%vh(2, 1:n) - read(iu, iostat=ierr, err=100) self%vh(3, 1:n) + read(iu, iostat=ierr, err=100) self%xh(1, :) + read(iu, iostat=ierr, err=100) self%xh(2, :) + read(iu, iostat=ierr, err=100) self%xh(3, :) + read(iu, iostat=ierr, err=100) self%vh(1, :) + read(iu, iostat=ierr, err=100) self%vh(2, :) + read(iu, iostat=ierr, err=100) self%vh(3, :) end select select type(pl => self) class is (swiftest_pl) ! Additional output if the passed polymorphic object is a massive body - read(iu, iostat=ierr, err=100) pl%Gmass(1:n) - pl%mass(1:n) = pl%Gmass / param%GU - if (param%lrhill_present) read(iu, iostat=ierr, err=100) pl%rhill(1:n) - read(iu, iostat=ierr, err=100) pl%radius(1:n) + read(iu, iostat=ierr, err=100) pl%Gmass(:) + pl%mass(:) = pl%Gmass(:) / param%GU + if (param%lrhill_present) read(iu, iostat=ierr, err=100) pl%rhill(:) + read(iu, iostat=ierr, err=100) pl%radius(:) if (param%lrotation) then - read(iu, iostat=ierr, err=100) pl%rot(1, 1:n) - read(iu, iostat=ierr, err=100) pl%rot(2, 1:n) - read(iu, iostat=ierr, err=100) pl%rot(3, 1:n) - read(iu, iostat=ierr, err=100) pl%Ip(1, 1:n) - read(iu, iostat=ierr, err=100) pl%Ip(2, 1:n) - read(iu, iostat=ierr, err=100) pl%Ip(3, 1:n) + read(iu, iostat=ierr, err=100) pl%rot(1, :) + read(iu, iostat=ierr, err=100) pl%rot(2, :) + read(iu, iostat=ierr, err=100) pl%rot(3, :) + read(iu, iostat=ierr, err=100) pl%Ip(1, :) + read(iu, iostat=ierr, err=100) pl%Ip(2, :) + read(iu, iostat=ierr, err=100) pl%Ip(3, :) end if if (param%ltides) then read(iu, iostat=ierr, err=100) pl%k2(1:n) From 68dc219936c079ccef86f16c0a898abb1fb613c6 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 17:15:27 -0400 Subject: [PATCH 37/42] Fixed bad ADD/SUB code for the mergeadd_list in symba_io --- src/symba/symba_io.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/symba/symba_io.f90 b/src/symba/symba_io.f90 index d3091155d..1f8626242 100644 --- a/src/symba/symba_io.f90 +++ b/src/symba/symba_io.f90 @@ -252,7 +252,7 @@ module subroutine symba_io_write_discard(self, param) nsub = mergesub_list%ncomp(isub) do j = 1, nadd if (iadd <= mergeadd_list%nbody) then - write(LUN, NAMEFMT) SUB, mergesub_list%id(iadd), mergesub_list%status(iadd) + write(LUN, NAMEFMT) ADD, mergesub_list%id(iadd), mergesub_list%status(iadd) write(LUN, VECFMT) mergeadd_list%xh(1, iadd), mergeadd_list%xh(2, iadd), mergeadd_list%xh(3, iadd) write(LUN, VECFMT) mergeadd_list%vh(1, iadd), mergeadd_list%vh(2, iadd), mergeadd_list%vh(3, iadd) else From cec408a7a6642ed9cac11da1222a457304e6f8fc Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 18:05:49 -0400 Subject: [PATCH 38/42] Added symba_discard_conserve_mtm code but have not troubleshooted all of the probems yet --- src/modules/symba_classes.f90 | 8 ++ src/symba/symba_collision.f90 | 9 +- src/symba/symba_discard.f90 | 166 ++++++++++++++++++++++++++++-- src/symba/symba_fragmentation.f90 | 2 +- src/symba/symba_util.f90 | 17 +++ 5 files changed, 190 insertions(+), 12 deletions(-) diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index b0daf9496..71df4b92e 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -95,6 +95,7 @@ module symba_classes procedure :: append => symba_util_append_pl !! Appends elements from one structure to another procedure :: fill => symba_util_fill_pl !! "Fills" bodies from one object into another depending on the results of a mask (uses the UNPACK intrinsic) procedure :: get_peri => symba_util_peri_pl !! Determine system pericenter passages for massive bodies + procedure :: rearray => symba_util_rearray_pl !! Clean up the massive body structures to remove discarded bodies and add new bodies procedure :: resize => symba_util_resize_pl !! Checks the current size of a SyMBA massive body against the requested size and resizes it if it is too small. procedure :: sort => symba_util_sort_pl !! Sorts body arrays by a sortable componen procedure :: rearrange => symba_util_sort_rearrange_pl !! Rearranges the order of array elements of body based on an input index array. Used in sorting methods @@ -533,6 +534,13 @@ module subroutine symba_util_peri_pl(self, system, param) class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters end subroutine symba_util_peri_pl + + module subroutine symba_util_rearray_pl(self, system, param) + implicit none + class(symba_pl), intent(inout) :: self !! SyMBA massive body object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + end subroutine symba_util_rearray_pl end interface interface util_resize diff --git a/src/symba/symba_collision.f90 b/src/symba/symba_collision.f90 index 0f8b4d519..ad0e64079 100644 --- a/src/symba/symba_collision.f90 +++ b/src/symba/symba_collision.f90 @@ -208,8 +208,8 @@ function symba_collision_consolidate_familes(pl, param, idx_parent, family, x, v fam_size = 2 + sum(nchild(:)) allocate(family(fam_size)) family = [parent_child_index_array(1)%idx(:),parent_child_index_array(2)%idx(:)] - fam_size = count(pl%status(family(:)) == COLLISION) - family = pack(family(:), pl%status(family(:)) == COLLISION) + fam_size = count(pl%lcollision(family(:))) + family = pack(family(:), pl%lcollision(family(:))) L_spin(:,:) = 0.0_DP Ip(:,:) = 0.0_DP @@ -226,8 +226,8 @@ function symba_collision_consolidate_familes(pl, param, idx_parent, family, x, v if (nchild(j) > 0) then do i = 1, nchild(j) ! Loop over all children and take the mass weighted mean of the properties idx_child = parent_child_index_array(j)%idx(i + 1) - if ((idx_child) /= COLLISION) cycle - mchild = pl%Gmass(idx_child) + if (.not. pl%lcollision(idx_child)) cycle + mchild = pl%mass(idx_child) xchild(:) = pl%xb(:, idx_child) vchild(:) = pl%vb(:, idx_child) volchild = (4.0_DP / 3.0_DP) * PI * pl%radius(idx_child)**3 @@ -266,6 +266,7 @@ function symba_collision_consolidate_familes(pl, param, idx_parent, family, x, v return end function symba_collision_consolidate_familes + module subroutine symba_collision_encounter_scrub(self, system, param) !! author: David A. Minton !! diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 1c5b4a732..f8ab11d04 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -58,6 +58,108 @@ subroutine symba_discard_cb_pl(pl, system, param) end subroutine symba_discard_cb_pl + subroutine symba_discard_conserve_mtm(pl, system, param, ipl, lescape_body) + !! author: David A. Minton + !! + !! Conserves system momentum when a body is lost from the system or collides with central body + implicit none + ! Arguments + class(symba_pl), intent(inout) :: pl + class(symba_nbody_system), intent(inout) :: system + class(symba_parameters), intent(inout) :: param + integer(I4B), intent(in) :: ipl + logical, intent(in) :: lescape_body + ! Internals + real(DP), dimension(NDIM) :: Lpl, Ltot, Lcb, xcom, vcom + real(DP) :: pe, ke_orbit, ke_spin + integer(I4B) :: i, oldstat + + select type(cb => system%cb) + class is (symba_cb) + + ! Add the potential and kinetic energy of the lost body to the records + pe = -cb%mass * pl%mass(ipl) / norm2(pl%xb(:, ipl) - pl%xb(:, 1)) + ke_orbit = 0.5_DP * pl%mass(ipl) * dot_product(pl%vb(:, ipl), pl%vb(:, ipl)) + if (param%lrotation) then + ke_spin = 0.5_DP * pl%mass(ipl) * pl%radius(ipl)**2 * pl%Ip(3, ipl) * dot_product(pl%rot(:, ipl), pl%rot(:, ipl)) + else + ke_spin = 0.0_DP + end if + + ! Add the pre-collision ke of the central body to the records + ! Add planet mass to central body accumulator + if (lescape_body) then + system%Mescape = system%Mescape + pl%mass(ipl) + do i = 1, npl + if (i == ipl) cycle + pe = pe - pl%mass(i) * pl%mass(ipl) / norm2(xb(:, ipl) - xb(:, i)) + end do + + Ltot(:) = 0.0_DP + do i = 1, npl + Lpl(:) = mass(i) * pl%xb(:,i) .cross. pl%vb(:, i) + Ltot(:) = Ltot(:) + Lpl(:) + end do + Ltot(:) = Ltot(:) + cb%mass * cb%xb(:) .cross. cb%vb(:) + call pl%b2h(cb) + oldstat = status(ipl) + pl%status(ipl) = INACTIVE + call pl%h2b(cb) + pl%status(ipl) = oldstat + do i = 1, npl + if (i == ipl) cycle + Lpl(:) = mass(i) * pl%xb(:,i) .cross. pl%vb(:, i) + Ltot(:) = Ltot(:) - Lpl(:) + end do + Ltot(:) = Ltot(:) - cb%mass * cb%xb(:) .cross. cb%vb(:) + system%Lescape(:) = system%Lescape(:) + system%Ltot(:) + if (param%lrotation) system%Lescape(:) = system%Lescape + pl%mass(ipl) * pl%radius(ipl)**2 * pl%Ip(3, ipl) * pl%rot(:, ipl) + + else + xcom(:) = (pl%mass(ipl) * pl%xb(:, ipl) + cb%mass * cb%xb(:)) / (cb%mass + pl%mass(ipl)) + vcom(:) = (pl%mass(ipl) * pl%vb(:, ipl) + cb%mass * cb%vb(:)) / (cb%mass + pl%mass(ipl)) + Lpl(:) = (pl%xb(:,ipl) - xcom(:)) .cross. pL%vb(:,ipl) - vcom(:) + if (param%lrotation) Lpl(:) = pl%mass(ipl) * (Lpl(:) + pl%radius(ipl)**2 * pl%Ip(3,ipl) * pl%rot(:, ipl)) + + Lcb(:) = cb%mass * (cb%xb(:) - xcom(:)) .cross. (cb%vb(:) - vcom(:)) + + ke_orbit = ke_orbit + 0.5_DP * cb%mass * dot_product(cb%vb(:), cb%vb(:)) + if (param%lrotation) ke_spin = ke_spin + 0.5_DP * cb%mass * cb%radius**2 * cb%Ip(3) * dot_product(cb%rot(:), cb%rot(:)) + ! Update mass of central body to be consistent with its total mass + cb%dM = cb%dM + pl%mass(ipl) + cb%dR = cb%dR + 1.0_DP / 3.0_DP * (pl%radius(ipl) / cb%radius)**3 - 2.0_DP / 9.0_DP * (pl%radius(ipl) / cb%radius)**6 + cb%mass = cb%M0 + cb%dM + cb%Gmass = param%GU * cb%mass + cb%radius = cb%R0 + cb%dR + param%rmin = cb%radius + ! Add planet angular momentum to central body accumulator + cb%dL(:) = Lpl(:) + Lcb(:) + cb%dL(:) + ! Update rotation of central body to by consistent with its angular momentum + if (param%lrotation) then + cb%rot(:) = (cb%L0(:) + cb%dL(:)) / (cb%Ip(3) * cb%mass * cb%radius**2) + ke_spin = ke_spin - 0.5_DP * cb%mass * cb%radius**2 * cb%Ip(3) * dot_product(cb%rot(:), cb%rot(:)) + end if + cb%xb(:) = xcom(:) + cb%vb(:) = vcom(:) + ke_orbit = ke_orbit - 0.5_DP * cb%mass * dot_product(cb%vb(:), cb%vb(:)) + end if + call pl%b2h(cb) + + ! We must do this for proper book-keeping, since we can no longer track this body's contribution to energy directly + if (lescape_body) then + system%Ecollisions = system%Ecollisions + ke_orbit + ke_spin + pe + system%Euntracked = system%Euntracked - (ke_orbit + ke_spin + pe) + else + system%Ecollisions = system%Ecollisions + pe + system%Euntracked = system%Euntracked - pe + end if + + end select + return + + end subroutine symba_discard_conserve_mtm + + subroutine symba_discard_nonplpl(pl, system, param) !! author: David A. Minton !! @@ -89,6 +191,45 @@ subroutine symba_discard_nonplpl(pl, system, param) end subroutine symba_discard_nonplpl + subroutine symba_discard_nonplpl_conservation(pl, system, param) + !! author: David A. Minton + !! + !! If there are any bodies that are removed due to either colliding with the central body or escaping the systme, + !! we need to track the conserved quantities with the system bookkeeping terms. + implicit none + ! Arguments + class(symba_pl), intent(inout) :: pl !! SyMBA test particle object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + integer(I4B) :: i, ndiscard, dstat + logical :: lescape + logical, dimension(pl%nbody) :: discard_l_pl + 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 + ndiscard = count(discard_l_pl(:)) + allocate(discard_index_list(ndiscard)) + discard_index_list(:) = pack([(i, i = 1, npl)], discard_l_pl(1:npl)) + do i = 1, ndiscard + dstat = pl%status(discard_index_list(i)) + if ((dstat == DISCARDED_RMIN) .or. (dstat == DISCARDED_PERI)) then + lescape = .false. + else if ((dstat == DISCARDED_RMAX) .or. (dstat == DISCARDED_RMAXU)) then + lescape = .true. + else + cycle + end if + ! Conserve all the quantities + call symba_discard_conserve_mtm(pl, system, param, discard_index_list(i), lescape) + end do + end associate + + return + end subroutine symba_discard_nonplpl_conservation + + subroutine symba_discard_peri_pl(pl, system, param) !! author: David A. Minton !! @@ -150,17 +291,28 @@ module subroutine symba_discard_pl(self, system, param) select type(param) class is (symba_parameters) associate(pl => self, plplenc_list => system%plplenc_list) + call pl%h2b(system%cb) + + ! First deal with the non pl-pl collisions call symba_discard_nonplpl(self, system, param) + + ! Scrub the pl-pl encounter list of any encounters that did not lead to a collision call plplenc_list%scrub_non_collision(system, param) - if (plplenc_list%nenc == 0) return ! No collisions to resolve - write(*, *) "Collision detected at time t = ",param%t - call pl%h2b(system%cb) - if (param%lfragmentation) then - call plplenc_list%resolve_fragmentations(system, param) - else - call plplenc_list%resolve_mergers(system, param) + if ((plplenc_list%nenc > 0) .and. any(pl%lcollision(:))) then + write(*, *) "Collision between massive bodies detected at time t = ",param%t + if (param%lfragmentation) then + call plplenc_list%resolve_fragmentations(system, param) + else + call plplenc_list%resolve_mergers(system, param) + end if end if + + if (any(pl%ldiscard(:))) then + call symba_discard_nonplpl_conservation(self, system, param) + call pl%rearray(self, system, param) + end if + end associate end select end select diff --git a/src/symba/symba_fragmentation.f90 b/src/symba/symba_fragmentation.f90 index ccc79892f..cafaacfd7 100644 --- a/src/symba/symba_fragmentation.f90 +++ b/src/symba/symba_fragmentation.f90 @@ -73,7 +73,7 @@ module function symba_fragmentation_casemerge(system, param, family, x, v, mass, pe = 0.0_DP do j = 1, nfamily do i = j + 1, nfamily - pe = pe - pl%Gmass(i) * pl%Gmass(j) / norm2(pl%xb(:, i) - pl%xb(:, j)) + pe = pe - pl%mass(i) * pl%mass(j) / norm2(pl%xb(:, i) - pl%xb(:, j)) end do end do system%Ecollisions = system%Ecollisions + pe diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index 7063e0910..c0276291a 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -369,6 +369,23 @@ module subroutine symba_util_peri_pl(self, system, param) end subroutine symba_util_peri_pl + module subroutine symba_util_rearray_pl(self, system, param) + !! Author: the Purdue Swiftest Team - David A. Minton, Carlisle A. Wishard, Jennifer L.L. Pouplin, and Jacob R. Elliott + !! + !! Clean up the massive body structures to remove discarded bodies and add new bodies + implicit none + ! Arguments + class(symba_pl), intent(inout) :: self !! SyMBA massive body object + class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + + ! First + + return + end subroutine symba_util_rearray_pl + + + module subroutine symba_util_resize_arr_info(arr, nnew) !! author: David A. Minton !! From ffd42d7b49a8a2f14d97966eb82cd394c3d791bc Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 18:06:13 -0400 Subject: [PATCH 39/42] Fixed bad cb index --- src/symba/symba_discard.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index f8ab11d04..63a38fc42 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -78,7 +78,7 @@ subroutine symba_discard_conserve_mtm(pl, system, param, ipl, lescape_body) class is (symba_cb) ! Add the potential and kinetic energy of the lost body to the records - pe = -cb%mass * pl%mass(ipl) / norm2(pl%xb(:, ipl) - pl%xb(:, 1)) + pe = -cb%mass * pl%mass(ipl) / norm2(pl%xb(:, ipl) - cb%xb(:)) ke_orbit = 0.5_DP * pl%mass(ipl) * dot_product(pl%vb(:, ipl), pl%vb(:, ipl)) if (param%lrotation) then ke_spin = 0.5_DP * pl%mass(ipl) * pl%radius(ipl)**2 * pl%Ip(3, ipl) * dot_product(pl%rot(:, ipl), pl%rot(:, ipl)) From cfedcd54e08c04d77606ed87d433ec46f8eca173 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 18:15:12 -0400 Subject: [PATCH 40/42] Fixed up typos and mismatched intents, allowing the discards to alter param%rmin --- src/discard/discard.f90 | 6 +++--- src/modules/rmvs_classes.f90 | 2 +- src/modules/swiftest_classes.f90 | 8 ++++---- src/modules/symba_classes.f90 | 2 +- src/rmvs/rmvs_discard.f90 | 2 +- src/symba/symba_discard.f90 | 24 ++++++++++++------------ 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/discard/discard.f90 b/src/discard/discard.f90 index 7dbbd95c2..be377e49e 100644 --- a/src/discard/discard.f90 +++ b/src/discard/discard.f90 @@ -10,7 +10,7 @@ module subroutine discard_system(self, param) implicit none ! Arguments class(swiftest_nbody_system), intent(inout) :: self !! Swiftest system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters ! Internals logical :: lany_discards @@ -36,7 +36,7 @@ module subroutine discard_pl(self, system, param) ! Arguments class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameter + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameter if (self%nbody == 0) return self%ldiscard(:) = .false. @@ -56,7 +56,7 @@ module subroutine discard_tp(self, system, param) ! Arguments class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameter + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameter associate(tp => self, ntp => self%nbody, cb => system%cb, pl => system%pl, npl => system%pl%nbody) if ((ntp == 0) .or. (npl ==0)) return diff --git a/src/modules/rmvs_classes.f90 b/src/modules/rmvs_classes.f90 index fbbfa15fe..4f7255237 100644 --- a/src/modules/rmvs_classes.f90 +++ b/src/modules/rmvs_classes.f90 @@ -114,7 +114,7 @@ module subroutine rmvs_discard_tp(self, system, param) implicit none class(rmvs_tp), intent(inout) :: self !! RMVS test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine rmvs_discard_tp module function rmvs_encounter_check_tp(self, system, dt) result(lencounter) diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 0fe43e391..74add9081 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -308,7 +308,7 @@ subroutine abstract_discard_body(self, 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) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine abstract_discard_body subroutine abstract_accel(self, system, param, t, lbeg) @@ -384,20 +384,20 @@ module subroutine discard_pl(self, system, param) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameter + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameter end subroutine discard_pl module subroutine discard_system(self, param) implicit none class(swiftest_nbody_system), intent(inout) :: self !! Swiftest system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine discard_system module subroutine discard_tp(self, system, param) implicit none class(swiftest_tp), intent(inout) :: self !! Swiftest test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine discard_tp module pure subroutine drift_all(mu, x, v, n, param, dt, mask, iflag) diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index 71df4b92e..c5aba1a7f 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -219,7 +219,7 @@ module subroutine symba_discard_pl(self, system, param) implicit none class(symba_pl), intent(inout) :: self !! SyMBA test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters end subroutine symba_discard_pl module subroutine symba_drift_pl(self, system, param, dt) diff --git a/src/rmvs/rmvs_discard.f90 b/src/rmvs/rmvs_discard.f90 index 551cdab92..bcdb9f902 100644 --- a/src/rmvs/rmvs_discard.f90 +++ b/src/rmvs/rmvs_discard.f90 @@ -13,7 +13,7 @@ module subroutine rmvs_discard_tp(self, system, param) ! Arguments class(rmvs_tp), intent(inout) :: self !! RMVS test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters ! Internals integer(I4B) :: i diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 63a38fc42..33fe47354 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -90,25 +90,25 @@ subroutine symba_discard_conserve_mtm(pl, system, param, ipl, lescape_body) ! Add planet mass to central body accumulator if (lescape_body) then system%Mescape = system%Mescape + pl%mass(ipl) - do i = 1, npl + do i = 1, pl%nbody if (i == ipl) cycle - pe = pe - pl%mass(i) * pl%mass(ipl) / norm2(xb(:, ipl) - xb(:, i)) + pe = pe - pl%mass(i) * pl%mass(ipl) / norm2(pl%xb(:, ipl) - pl%xb(:, i)) end do Ltot(:) = 0.0_DP - do i = 1, npl - Lpl(:) = mass(i) * pl%xb(:,i) .cross. pl%vb(:, i) + do i = 1, pl%nbody + Lpl(:) = pL%mass(i) * pl%xb(:,i) .cross. pl%vb(:, i) Ltot(:) = Ltot(:) + Lpl(:) end do Ltot(:) = Ltot(:) + cb%mass * cb%xb(:) .cross. cb%vb(:) call pl%b2h(cb) - oldstat = status(ipl) + oldstat = pl%status(ipl) pl%status(ipl) = INACTIVE call pl%h2b(cb) pl%status(ipl) = oldstat - do i = 1, npl + do i = 1, pl%nbody if (i == ipl) cycle - Lpl(:) = mass(i) * pl%xb(:,i) .cross. pl%vb(:, i) + Lpl(:) = pl%mass(i) * pl%xb(:,i) .cross. pl%vb(:, i) Ltot(:) = Ltot(:) - Lpl(:) end do Ltot(:) = Ltot(:) - cb%mass * cb%xb(:) .cross. cb%vb(:) @@ -198,9 +198,9 @@ subroutine symba_discard_nonplpl_conservation(pl, system, param) !! we need to track the conserved quantities with the system bookkeeping terms. implicit none ! Arguments - class(symba_pl), intent(inout) :: pl !! SyMBA test particle object - class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(symba_pl), intent(inout) :: pl !! SyMBA test particle object + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(symba_parameters), intent(inout) :: param !! Current run configuration parameters ! Internals integer(I4B) :: i, ndiscard, dstat logical :: lescape @@ -284,7 +284,7 @@ module subroutine symba_discard_pl(self, system, param) ! Arguments class(symba_pl), intent(inout) :: self !! SyMBA test particle object class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(swiftest_parameters), intent(inout) :: param !! Current run configuration parameters select type(system) class is (symba_nbody_system) @@ -310,7 +310,7 @@ module subroutine symba_discard_pl(self, system, param) if (any(pl%ldiscard(:))) then call symba_discard_nonplpl_conservation(self, system, param) - call pl%rearray(self, system, param) + !call pl%rearray(self, system, param) end if end associate From 5dee8d3788949f716f15f225678a894b17a1e428 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 19:41:44 -0400 Subject: [PATCH 41/42] Reorganized io subroutines into alphabetical order like the other submodules --- .../swiftest_vs_swifter.ipynb | 1208 ++++++++++++++++- src/io/io.f90 | 732 +++++----- src/modules/symba_classes.f90 | 6 +- src/symba/symba_discard.f90 | 2 +- src/symba/symba_fragmentation.f90 | 2 + src/symba/symba_util.f90 | 30 +- src/util/util_spill.f90 | 1 + 7 files changed, 1540 insertions(+), 441 deletions(-) diff --git a/examples/symba_swifter_comparison/1pl_1pl_encounter/swiftest_vs_swifter.ipynb b/examples/symba_swifter_comparison/1pl_1pl_encounter/swiftest_vs_swifter.ipynb index 69349f2a4..3a80eebd1 100644 --- a/examples/symba_swifter_comparison/1pl_1pl_encounter/swiftest_vs_swifter.ipynb +++ b/examples/symba_swifter_comparison/1pl_1pl_encounter/swiftest_vs_swifter.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -35,7 +35,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -57,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -66,7 +66,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -75,23 +75,23 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[,\n", - " ]" + "[,\n", + " ]" ] }, - "execution_count": 6, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
    " ] @@ -108,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -466,74 +466,1150 @@ " fill: currentColor;\n", "}\n", "
    <xarray.DataArray 'vx' (time (y): 221)>\n",
    -       "array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,\n",
    -       "        0.,  0., nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,\n",
    -       "       nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan])\n",
    +       "array([0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "...\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.        , 0.        , 0.        ,\n",
    +       "       0.        , 0.        , 0.02101973, 0.02102004, 0.02102057,\n",
    +       "       0.0210213 , 0.02102224, 0.02102336, 0.02102465, 0.02102612,\n",
    +       "       0.02102774, 0.02102951, 0.02103142, 0.02103346, 0.02103561,\n",
    +       "       0.02103787, 0.02104022, 0.02104267, 0.02104519, 0.02104778,\n",
    +       "       0.02105043, 0.02105312, 0.02105586, 0.02105862, 0.0210614 ,\n",
    +       "       0.02106419])\n",
            "Coordinates:\n",
    -       "    id        float64 100.0\n",
    -       "  * time (y)  (time (y)) float64 0.0 0.0006845 0.001369 ... 0.1492 0.1499 0.1506
    " + " id float64 2.0\n", + " * time (y) (time (y)) float64 0.0 0.0006845 0.001369 ... 0.1492 0.1499 0.1506" ], "text/plain": [ "\n", - "array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n", - " 0., 0., nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan,\n", - " nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan])\n", + "array([0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + "...\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0. , 0. , 0. ,\n", + " 0. , 0. , 0.02101973, 0.02102004, 0.02102057,\n", + " 0.0210213 , 0.02102224, 0.02102336, 0.02102465, 0.02102612,\n", + " 0.02102774, 0.02102951, 0.02103142, 0.02103346, 0.02103561,\n", + " 0.02103787, 0.02104022, 0.02104267, 0.02104519, 0.02104778,\n", + " 0.02105043, 0.02105312, 0.02105586, 0.02105862, 0.0210614 ,\n", + " 0.02106419])\n", "Coordinates:\n", - " id float64 100.0\n", + " id float64 2.0\n", " * time (y) (time (y)) float64 0.0 0.0006845 0.001369 ... 0.1492 0.1499 0.1506" ] }, - "execution_count": 7, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "swiftdiff['vx'].sel(id=100)" + "swiftdiff['vx'].sel(id=2)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    <xarray.DataArray 'vx' (time: 221)>\n",
    +       "array([ 0.        , -0.02730963, -0.05461883, -0.08192718, -0.10923426,\n",
    +       "       -0.13653965, -0.16384292, -0.19114364, -0.21844141, -0.24573578,\n",
    +       "       -0.27302634, -0.30031266, -0.32759433, -0.35487091, -0.38214199,\n",
    +       "       -0.40940715, -0.43666596, -0.463918  , -0.49116285, -0.51840009,\n",
    +       "       -0.5456293 , -0.57285005, -0.60006193, -0.62726452, -0.6544574 ,\n",
    +       "       -0.68164014, -0.70881234, -0.73597358, -0.76312342, -0.79026147,\n",
    +       "       -0.8173873 , -0.8445005 , -0.87160064, -0.89868733, -0.92576014,\n",
    +       "       -0.95281866, -0.97986247, -1.00689117, -1.03390434, -1.06090158,\n",
    +       "       -1.08788246, -1.11484659, -1.14179356, -1.16872296, -1.19563437,\n",
    +       "       -1.22252741, -1.24940165, -1.27625671, -1.30309216, -1.32990762,\n",
    +       "       -1.35670269, -1.38347696, -1.41023003, -1.43696151, -1.463671  ,\n",
    +       "       -1.4903581 , -1.51702243, -1.54366359, -1.57028119, -1.59687484,\n",
    +       "       -1.62344416, -1.64998874, -1.67650822, -1.70300221, -1.72947032,\n",
    +       "       -1.75591217, -1.78232739, -1.8087156 , -1.83507643, -1.8614095 ,\n",
    +       "       -1.88771444, -1.91399088, -1.94023846, -1.96645681, -1.99264557,\n",
    +       "       -2.01880437, -2.04493287, -2.0710307 , -2.09709752, -2.12313297,\n",
    +       "       -2.1491367 , -2.17510838, -2.20104766, -2.2269542 , -2.25282767,\n",
    +       "       -2.27866774, -2.30447407, -2.33024634, -2.35598424, -2.38168744,\n",
    +       "       -2.40735563, -2.43298851, -2.45858576, -2.48414708, -2.50967219,\n",
    +       "       -2.53516079, -2.56061259, -2.58602731, -2.61140468, -2.63674443,\n",
    +       "...\n",
    +       "       -3.28166908, -3.30592115, -3.33013189, -3.3543014 , -3.37842979,\n",
    +       "       -3.40251722, -3.42656386, -3.45056991, -3.47453562, -3.49846126,\n",
    +       "       -3.52234715, -3.54619364, -3.57000113, -3.59377005, -3.61750092,\n",
    +       "       -3.64119426, -3.66485068, -3.68847086, -3.71205553, -3.73560548,\n",
    +       "       -3.75912161, -3.78260489, -3.80605637, -3.82947723, -3.85286873,\n",
    +       "       -3.87623226, -3.89956936, -3.92288168, -3.94617105, -3.96943947,\n",
    +       "       -3.99268912, -4.01592242, -4.03914199, -4.06235073, -4.08555183,\n",
    +       "       -4.10874879, -4.13194551, -4.15514625, -4.17835577, -4.20157933,\n",
    +       "       -4.2248228 , -4.24809272, -4.2713964 , -4.29474206, -4.31813893,\n",
    +       "       -4.34159746, -4.36512951, -4.38874856, -4.41247007, -4.43631182,\n",
    +       "       -4.46029439, -4.48444172, -4.50878191, -4.53334814, -4.55817998,\n",
    +       "       -4.58332498, -4.60884098, -4.63479915, -4.66128825, -4.68842081,\n",
    +       "       -4.71634199, -4.7452432 , -4.77538326, -4.80712299, -4.84098468,\n",
    +       "       -4.87776098, -4.91873117, -4.96614064, -5.02443531, -5.10428159,\n",
    +       "       -5.24263186, -5.9750488 ,         nan,         nan,         nan,\n",
    +       "               nan,         nan,         nan,         nan,         nan,\n",
    +       "               nan,         nan,         nan,         nan,         nan,\n",
    +       "               nan,         nan,         nan,         nan,         nan,\n",
    +       "               nan,         nan,         nan,         nan,         nan,\n",
    +       "               nan])\n",
    +       "Coordinates:\n",
    +       "    id       float64 100.0\n",
    +       "  * time     (time) float64 0.0 0.0006845 0.001369 ... 0.1492 0.1499 0.1506
    " + ], + "text/plain": [ + "\n", + "array([ 0. , -0.02730963, -0.05461883, -0.08192718, -0.10923426,\n", + " -0.13653965, -0.16384292, -0.19114364, -0.21844141, -0.24573578,\n", + " -0.27302634, -0.30031266, -0.32759433, -0.35487091, -0.38214199,\n", + " -0.40940715, -0.43666596, -0.463918 , -0.49116285, -0.51840009,\n", + " -0.5456293 , -0.57285005, -0.60006193, -0.62726452, -0.6544574 ,\n", + " -0.68164014, -0.70881234, -0.73597358, -0.76312342, -0.79026147,\n", + " -0.8173873 , -0.8445005 , -0.87160064, -0.89868733, -0.92576014,\n", + " -0.95281866, -0.97986247, -1.00689117, -1.03390434, -1.06090158,\n", + " -1.08788246, -1.11484659, -1.14179356, -1.16872296, -1.19563437,\n", + " -1.22252741, -1.24940165, -1.27625671, -1.30309216, -1.32990762,\n", + " -1.35670269, -1.38347696, -1.41023003, -1.43696151, -1.463671 ,\n", + " -1.4903581 , -1.51702243, -1.54366359, -1.57028119, -1.59687484,\n", + " -1.62344416, -1.64998874, -1.67650822, -1.70300221, -1.72947032,\n", + " -1.75591217, -1.78232739, -1.8087156 , -1.83507643, -1.8614095 ,\n", + " -1.88771444, -1.91399088, -1.94023846, -1.96645681, -1.99264557,\n", + " -2.01880437, -2.04493287, -2.0710307 , -2.09709752, -2.12313297,\n", + " -2.1491367 , -2.17510838, -2.20104766, -2.2269542 , -2.25282767,\n", + " -2.27866774, -2.30447407, -2.33024634, -2.35598424, -2.38168744,\n", + " -2.40735563, -2.43298851, -2.45858576, -2.48414708, -2.50967219,\n", + " -2.53516079, -2.56061259, -2.58602731, -2.61140468, -2.63674443,\n", + "...\n", + " -3.28166908, -3.30592115, -3.33013189, -3.3543014 , -3.37842979,\n", + " -3.40251722, -3.42656386, -3.45056991, -3.47453562, -3.49846126,\n", + " -3.52234715, -3.54619364, -3.57000113, -3.59377005, -3.61750092,\n", + " -3.64119426, -3.66485068, -3.68847086, -3.71205553, -3.73560548,\n", + " -3.75912161, -3.78260489, -3.80605637, -3.82947723, -3.85286873,\n", + " -3.87623226, -3.89956936, -3.92288168, -3.94617105, -3.96943947,\n", + " -3.99268912, -4.01592242, -4.03914199, -4.06235073, -4.08555183,\n", + " -4.10874879, -4.13194551, -4.15514625, -4.17835577, -4.20157933,\n", + " -4.2248228 , -4.24809272, -4.2713964 , -4.29474206, -4.31813893,\n", + " -4.34159746, -4.36512951, -4.38874856, -4.41247007, -4.43631182,\n", + " -4.46029439, -4.48444172, -4.50878191, -4.53334814, -4.55817998,\n", + " -4.58332498, -4.60884098, -4.63479915, -4.66128825, -4.68842081,\n", + " -4.71634199, -4.7452432 , -4.77538326, -4.80712299, -4.84098468,\n", + " -4.87776098, -4.91873117, -4.96614064, -5.02443531, -5.10428159,\n", + " -5.24263186, -5.9750488 , nan, nan, nan,\n", + " nan, nan, nan, nan, nan,\n", + " nan, nan, nan, nan, nan,\n", + " nan, nan, nan, nan, nan,\n", + " nan, nan, nan, nan, nan,\n", + " nan])\n", + "Coordinates:\n", + " id float64 100.0\n", + " * time (time) float64 0.0 0.0006845 0.001369 ... 0.1492 0.1499 0.1506" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "swiftestsim.ds.sel(id=100)['vx']" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
    \n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
    <xarray.DataArray 'vx' (time: 221)>\n",
    +       "array([ 0.        , -0.02730963, -0.05461883, -0.08192718, -0.10923426,\n",
    +       "       -0.13653965, -0.16384292, -0.19114364, -0.21844141, -0.24573578,\n",
    +       "       -0.27302634, -0.30031266, -0.32759433, -0.35487091, -0.38214199,\n",
    +       "       -0.40940715, -0.43666596, -0.463918  , -0.49116285, -0.51840009,\n",
    +       "       -0.5456293 , -0.57285005, -0.60006193, -0.62726452, -0.6544574 ,\n",
    +       "       -0.68164014, -0.70881234, -0.73597358, -0.76312342, -0.79026147,\n",
    +       "       -0.8173873 , -0.8445005 , -0.87160064, -0.89868733, -0.92576014,\n",
    +       "       -0.95281866, -0.97986247, -1.00689117, -1.03390434, -1.06090158,\n",
    +       "       -1.08788246, -1.11484659, -1.14179356, -1.16872296, -1.19563437,\n",
    +       "       -1.22252741, -1.24940165, -1.27625671, -1.30309216, -1.32990762,\n",
    +       "       -1.35670269, -1.38347696, -1.41023003, -1.43696151, -1.463671  ,\n",
    +       "       -1.4903581 , -1.51702243, -1.54366359, -1.57028119, -1.59687484,\n",
    +       "       -1.62344416, -1.64998874, -1.67650822, -1.70300221, -1.72947032,\n",
    +       "       -1.75591217, -1.78232739, -1.8087156 , -1.83507643, -1.8614095 ,\n",
    +       "       -1.88771444, -1.91399088, -1.94023846, -1.96645681, -1.99264557,\n",
    +       "       -2.01880437, -2.04493287, -2.0710307 , -2.09709752, -2.12313297,\n",
    +       "       -2.1491367 , -2.17510838, -2.20104766, -2.2269542 , -2.25282767,\n",
    +       "       -2.27866774, -2.30447407, -2.33024634, -2.35598424, -2.38168744,\n",
    +       "       -2.40735563, -2.43298851, -2.45858576, -2.48414708, -2.50967219,\n",
    +       "       -2.53516079, -2.56061259, -2.58602731, -2.61140468, -2.63674443,\n",
    +       "...\n",
    +       "       -3.28166908, -3.30592115, -3.33013189, -3.3543014 , -3.37842979,\n",
    +       "       -3.40251722, -3.42656386, -3.45056991, -3.47453562, -3.49846126,\n",
    +       "       -3.52234715, -3.54619364, -3.57000113, -3.59377005, -3.61750092,\n",
    +       "       -3.64119426, -3.66485068, -3.68847086, -3.71205553, -3.73560548,\n",
    +       "       -3.75912161, -3.78260489, -3.80605637, -3.82947723, -3.85286873,\n",
    +       "       -3.87623226, -3.89956936, -3.92288168, -3.94617105, -3.96943947,\n",
    +       "       -3.99268912, -4.01592242, -4.03914199, -4.06235073, -4.08555183,\n",
    +       "       -4.10874879, -4.13194551, -4.15514625, -4.17835577, -4.20157933,\n",
    +       "       -4.2248228 , -4.24809272, -4.2713964 , -4.29474206, -4.31813893,\n",
    +       "       -4.34159746, -4.36512951, -4.38874856, -4.41247007, -4.43631182,\n",
    +       "       -4.46029439, -4.48444172, -4.50878191, -4.53334814, -4.55817998,\n",
    +       "       -4.58332498, -4.60884098, -4.63479915, -4.66128825, -4.68842081,\n",
    +       "       -4.71634199, -4.7452432 , -4.77538326, -4.80712299, -4.84098468,\n",
    +       "       -4.87776098, -4.91873117, -4.96614064, -5.02443531, -5.10428159,\n",
    +       "       -5.24263186, -5.9750488 ,         nan,         nan,         nan,\n",
    +       "               nan,         nan,         nan,         nan,         nan,\n",
    +       "               nan,         nan,         nan,         nan,         nan,\n",
    +       "               nan,         nan,         nan,         nan,         nan,\n",
    +       "               nan,         nan,         nan,         nan,         nan,\n",
    +       "               nan])\n",
    +       "Coordinates:\n",
    +       "    id       int64 100\n",
    +       "  * time     (time) float64 0.0 0.0006845 0.001369 ... 0.1492 0.1499 0.1506
    " + ], + "text/plain": [ + "\n", + "array([ 0. , -0.02730963, -0.05461883, -0.08192718, -0.10923426,\n", + " -0.13653965, -0.16384292, -0.19114364, -0.21844141, -0.24573578,\n", + " -0.27302634, -0.30031266, -0.32759433, -0.35487091, -0.38214199,\n", + " -0.40940715, -0.43666596, -0.463918 , -0.49116285, -0.51840009,\n", + " -0.5456293 , -0.57285005, -0.60006193, -0.62726452, -0.6544574 ,\n", + " -0.68164014, -0.70881234, -0.73597358, -0.76312342, -0.79026147,\n", + " -0.8173873 , -0.8445005 , -0.87160064, -0.89868733, -0.92576014,\n", + " -0.95281866, -0.97986247, -1.00689117, -1.03390434, -1.06090158,\n", + " -1.08788246, -1.11484659, -1.14179356, -1.16872296, -1.19563437,\n", + " -1.22252741, -1.24940165, -1.27625671, -1.30309216, -1.32990762,\n", + " -1.35670269, -1.38347696, -1.41023003, -1.43696151, -1.463671 ,\n", + " -1.4903581 , -1.51702243, -1.54366359, -1.57028119, -1.59687484,\n", + " -1.62344416, -1.64998874, -1.67650822, -1.70300221, -1.72947032,\n", + " -1.75591217, -1.78232739, -1.8087156 , -1.83507643, -1.8614095 ,\n", + " -1.88771444, -1.91399088, -1.94023846, -1.96645681, -1.99264557,\n", + " -2.01880437, -2.04493287, -2.0710307 , -2.09709752, -2.12313297,\n", + " -2.1491367 , -2.17510838, -2.20104766, -2.2269542 , -2.25282767,\n", + " -2.27866774, -2.30447407, -2.33024634, -2.35598424, -2.38168744,\n", + " -2.40735563, -2.43298851, -2.45858576, -2.48414708, -2.50967219,\n", + " -2.53516079, -2.56061259, -2.58602731, -2.61140468, -2.63674443,\n", + "...\n", + " -3.28166908, -3.30592115, -3.33013189, -3.3543014 , -3.37842979,\n", + " -3.40251722, -3.42656386, -3.45056991, -3.47453562, -3.49846126,\n", + " -3.52234715, -3.54619364, -3.57000113, -3.59377005, -3.61750092,\n", + " -3.64119426, -3.66485068, -3.68847086, -3.71205553, -3.73560548,\n", + " -3.75912161, -3.78260489, -3.80605637, -3.82947723, -3.85286873,\n", + " -3.87623226, -3.89956936, -3.92288168, -3.94617105, -3.96943947,\n", + " -3.99268912, -4.01592242, -4.03914199, -4.06235073, -4.08555183,\n", + " -4.10874879, -4.13194551, -4.15514625, -4.17835577, -4.20157933,\n", + " -4.2248228 , -4.24809272, -4.2713964 , -4.29474206, -4.31813893,\n", + " -4.34159746, -4.36512951, -4.38874856, -4.41247007, -4.43631182,\n", + " -4.46029439, -4.48444172, -4.50878191, -4.53334814, -4.55817998,\n", + " -4.58332498, -4.60884098, -4.63479915, -4.66128825, -4.68842081,\n", + " -4.71634199, -4.7452432 , -4.77538326, -4.80712299, -4.84098468,\n", + " -4.87776098, -4.91873117, -4.96614064, -5.02443531, -5.10428159,\n", + " -5.24263186, -5.9750488 , nan, nan, nan,\n", + " nan, nan, nan, nan, nan,\n", + " nan, nan, nan, nan, nan,\n", + " nan, nan, nan, nan, nan,\n", + " nan, nan, nan, nan, nan,\n", + " nan])\n", + "Coordinates:\n", + " id int64 100\n", + " * time (time) float64 0.0 0.0006845 0.001369 ... 0.1492 0.1499 0.1506" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "swiftersim.ds.sel(id=100)['vx']" ] }, { diff --git a/src/io/io.f90 b/src/io/io.f90 index d2791aa92..145752836 100644 --- a/src/io/io.f90 +++ b/src/io/io.f90 @@ -2,6 +2,238 @@ use swiftest contains + module subroutine io_dump_param(self, param_file_name) + !! author: David A. Minton + !! + !! Dump integration parameters to file + !! + !! Adapted from David E. Kaufmann's Swifter routine io_dump_param.f90 + !! Adapted from Martin Duncan's Swift routine io_dump_param.f + implicit none + ! Arguments + 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) + ! Internals + integer(I4B), parameter :: LUN = 7 !! Unit number of output file + integer(I4B) :: ierr !! Error code + character(STRMAX) :: error_message !! Error message in UDIO procedure + + open(unit = LUN, file = param_file_name, status='replace', form = 'FORMATTED', iostat =ierr) + if (ierr /=0) then + write(*,*) 'Swiftest error.' + write(*,*) ' Could not open dump file: ',trim(adjustl(param_file_name)) + call util_exit(FAILURE) + end if + + !! todo: Currently this procedure does not work in user-defined derived-type input mode + !! due to compiler incompatabilities + !write(LUN,'(DT)') param + call self%writer(LUN, iotype = "none", v_list = [0], iostat = ierr, iomsg = error_message) + if (ierr /= 0) then + write(*,*) trim(adjustl(error_message)) + call util_exit(FAILURE) + end if + close(LUN) + + return + end subroutine io_dump_param + + + module subroutine io_dump_swiftest(self, param, msg) + !! author: David A. Minton + !! + !! Dump massive body data to files + !! + !! Adapted from David E. Kaufmann's Swifter routine: io_dump_pl.f90 and io_dump_tp.f90 + !! Adapted from Hal Levison's Swift routine io_dump_pl.f and io_dump_tp.f + implicit none + ! Arguments + class(swiftest_base), intent(inout) :: self !! Swiftest base object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + character(*), optional, intent(in) :: msg !! Message to display with dump operation + ! Internals + integer(I4B) :: ierr !! Error code + integer(I4B),parameter :: LUN = 7 !! Unit number for dump file + integer(I4B) :: iu = LUN + character(len=:), allocatable :: dump_file_name + + select type(self) + class is(swiftest_cb) + dump_file_name = trim(adjustl(param%incbfile)) + class is (swiftest_pl) + dump_file_name = trim(adjustl(param%inplfile)) + class is (swiftest_tp) + dump_file_name = trim(adjustl(param%intpfile)) + end select + open(unit = iu, file = dump_file_name, form = "UNFORMATTED", status = 'replace', iostat = ierr) + if (ierr /= 0) then + write(*, *) "Swiftest error:" + write(*, *) " Unable to open binary dump file " // dump_file_name + call util_exit(FAILURE) + end if + call self%write_frame(iu, param) + close(LUN) + + return + end subroutine io_dump_swiftest + + + module subroutine io_dump_system(self, param, msg) + !! author: David A. Minton + !! + !! Dumps the state of the system to files in case the simulation is interrupted. + !! As a safety mechanism, there are two dump files that are written in alternating order + !! so that if a dump file gets corrupted during writing, the user can restart from the older one. + implicit none + ! Arguments + class(swiftest_nbody_system), intent(inout) :: self !! Swiftest system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + character(*), optional, intent(in) :: msg !! Message to display with dump operation + ! Internals + class(swiftest_parameters), allocatable :: dump_param !! Local parameters variable used to parameters change input file names + !! to dump file-specific values without changing the user-defined values + integer(I4B), save :: idx = 1 !! Index of current dump file. Output flips between 2 files for extra security + !! in case the program halts during writing + character(len=:), allocatable :: param_file_name + real(DP) :: tfrac + + allocate(dump_param, source=param) + param_file_name = trim(adjustl(DUMP_PARAM_FILE(idx))) + dump_param%incbfile = trim(adjustl(DUMP_CB_FILE(idx))) + dump_param%inplfile = trim(adjustl(DUMP_PL_FILE(idx))) + dump_param%intpfile = trim(adjustl(DUMP_TP_FILE(idx))) + dump_param%out_form = XV + dump_param%out_stat = 'APPEND' + dump_param%T0 = param%t + call dump_param%dump(param_file_name) + + call self%cb%dump(dump_param) + if (self%pl%nbody > 0) call self%pl%dump(dump_param) + if (self%tp%nbody > 0) call self%tp%dump(dump_param) + + idx = idx + 1 + if (idx > NDUMPFILES) idx = 1 + + ! Print the status message (format code passed in from main driver) + tfrac = (param%t - param%t0) / (param%tstop - param%t0) + write(*,msg) param%t, tfrac, self%pl%nbody, self%tp%nbody + + return + end subroutine io_dump_system + + + module function io_get_args(integrator, param_file_name) result(ierr) + !! author: David A. Minton + !! + !! Reads in the name of the parameter file from command line arguments. + implicit none + ! Arguments + integer(I4B) :: integrator !! Symbolic code of the requested integrator + character(len=:), allocatable :: param_file_name !! Name of the input parameters file + ! Result + integer(I4B) :: ierr !! I/O error code + ! Internals + character(len=STRMAX) :: arg1, arg2 + integer :: narg,ierr_arg1, ierr_arg2 + character(len=*),parameter :: linefmt = '(A)' + + ierr = -1 ! Default is to fail + narg = command_argument_count() ! + if (narg == 2) then + call get_command_argument(1, arg1, status = ierr_arg1) + call get_command_argument(2, arg2, status = ierr_arg2) + if ((ierr_arg1 == 0) .and. (ierr_arg2 == 0)) then + ierr = 0 + call io_toupper(arg1) + select case(arg1) + case('BS') + integrator = BS + case('HELIO') + integrator = HELIO + case('RA15') + integrator = RA15 + case('TU4') + integrator = TU4 + case('WHM') + integrator = WHM + case('RMVS') + integrator = RMVS + case('SYMBA') + integrator = SYMBA + case('RINGMOONS') + integrator = RINGMOONS + case default + integrator = UNKNOWN_INTEGRATOR + write(*,*) trim(adjustl(arg1)) // ' is not a valid integrator.' + ierr = -1 + end select + param_file_name = trim(adjustl(arg2)) + end if + else + call get_command_argument(1, arg1, status = ierr_arg1) + if (ierr_arg1 == 0) then + if (arg1 == '-v' .or. arg1 == '--version') then + call util_version() + else if (arg1 == '-h' .or. arg1 == '--help') then + call util_exit(HELP) + end if + end if + end if + if (ierr /= 0) call util_exit(USAGE) + + return + end function io_get_args + + + module function io_get_token(buffer, ifirst, ilast, ierr) result(token) + !! author: David A. Minton + !! + !! Retrieves a character token from an input string. Here a token is defined as any set of contiguous non-blank characters not + !! beginning with or containing "!". If "!" is present, any remaining part of the buffer including the "!" is ignored + !! + !! Adapted from David E. Kaufmann's Swifter routine io_get_token.f90 + implicit none + ! Arguments + 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 + ! Result + character(len=:), allocatable :: token !! Returned token string + ! Internals + integer(I4B) :: i,ilength + + ilength = len(buffer) + + if (ifirst > ilength) then + ilast = ifirst + ierr = -1 !! Bad input + token = '' + return + end if + do i = ifirst, ilength + if (buffer(i:i) /= ' ') exit + end do + if ((i > ilength) .or. (buffer(i:i) == '!')) then + ifirst = i + ilast = i + ierr = -2 !! No valid token + token = '' + return + end if + ifirst = i + do i = ifirst, ilength + if ((buffer(i:i) == ' ') .or. (buffer(i:i) == '!')) exit + end do + ilast = i - 1 + ierr = 0 + + token = buffer(ifirst:ilast) + + return + end function io_get_token + + module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg) !! author: The Purdue Swiftest Team - David A. Minton, Carlisle A. Wishard, Jennifer L.L. Pouplin, and Jacob R. Elliott !! @@ -257,342 +489,110 @@ module subroutine io_param_reader(self, unit, iotype, v_list, iostat, iomsg) ! Calculate the G for the system units self%GU = GC / (self%DU2M**3 / (self%MU2KG * self%TU2S**2)) - ! Calculate the inverse speed of light in the system units - self%inv_c2 = einsteinC * self%TU2S / self%DU2M - self%inv_c2 = (self%inv_c2)**(-2) - - associate(integrator => v_list(1)) - if (integrator == RMVS) then - if (.not.self%lclose) then - write(iomsg,*) 'This integrator requires CHK_CLOSE to be enabled.' - iostat = -1 - return - end if - end if - - ! Determine if the GR flag is set correctly for this integrator - select case(integrator) - case(WHM, RMVS, HELIO, SYMBA) - write(*,*) "GR = ", self%lgr - case default - if (self%lgr) write(iomsg, *) 'GR is not yet implemented for this integrator. This parameter will be ignored.' - self%lgr = .false. - end select - end associate - - iostat = 0 - - return - end subroutine io_param_reader - - - module subroutine io_param_writer(self, unit, iotype, v_list, iostat, iomsg) - !! author: David A. Minton - !! - !! Dump integration parameters to file - !! - !! Adapted from David E. Kaufmann's Swifter routine io_dump_param.f90 - !! Adapted from Martin Duncan's Swift routine io_dump_param.f - implicit none - ! Arguments - class(swiftest_parameters),intent(in) :: self !! Collection of parameters - integer, intent(in) :: unit !! File unit number - character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT. - !! If you do not include a char-literal-constant, the iotype argument contains only DT. - integer, intent(in) :: v_list(:) !! Not used in this procedure - integer, intent(out) :: iostat !! IO status code - character(len=*), intent(inout) :: iomsg !! Message to pass if iostat /= 0 - ! Internals - character(*),parameter :: Ifmt = '(I0)' !! Format label for integer values - character(*),parameter :: Rfmt = '(ES25.17)' !! Format label for real values - character(*),parameter :: Rarrfmt = '(3(ES25.17,1X))' !! Format label for real values - character(*),parameter :: Lfmt = '(L1)' !! Format label for logical values - character(len=*), parameter :: Afmt = '(A25,1X,64(:,A25,1X))' - character(256) :: param_name, param_value - type character_array - character(25) :: value - end type character_array - type(character_array), dimension(:), allocatable :: param_array - integer(I4B) :: i - - associate(param => self) - write(param_name, Afmt) "T0"; write(param_value,Rfmt) param%t0; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "TSTOP"; write(param_value, Rfmt) param%tstop; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "DT"; write(param_value, Rfmt) param%dt; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "PL_IN"; write(param_value, Afmt) trim(adjustl(param%inplfile)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "TP_in"; write(param_value, Afmt) trim(adjustl(param%intpfile)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "IN_TYPE"; write(param_value, Afmt) trim(adjustl(param%in_type)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) - if (param%istep_out > 0) then - write(param_name, Afmt) "ISTEP_OUT"; write(param_value, Ifmt) param%istep_out; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "BIN_OUT"; write(param_value, Afmt) trim(adjustl(param%outfile)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "OUT_TYPE"; write(param_value, Afmt) trim(adjustl(param%out_type)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "OUT_FORM"; write(param_value, Afmt) trim(adjustl(param%out_form)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "OUT_STAT"; write(param_value, Afmt) "APPEND"; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - end if - write(param_name, Afmt) "ENC_OUT"; write(param_value, Afmt) trim(adjustl(param%enc_out)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) - if (param%istep_dump > 0) then - write(param_name, Afmt) "ISTEP_DUMP"; write(param_value, Ifmt) param%istep_dump; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - end if - write(param_name, Afmt) "CHK_RMIN"; write(param_value, Rfmt) param%rmin; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "CHK_RMAX"; write(param_value, Rfmt) param%rmax; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "CHK_EJECT"; write(param_value, Rfmt) param%rmaxu; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "CHK_QMIN"; write(param_value, Rfmt) param%qmin; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - if (param%qmin >= 0.0_DP) then - write(param_name, Afmt) "CHK_QMIN_COORD"; write(param_value, Afmt) trim(adjustl(param%qmin_coord)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) - allocate(param_array(2)) - write(param_array(1)%value, Rfmt) param%qmin_alo - write(param_array(2)%value, Rfmt) param%qmin_ahi - write(param_name, Afmt) "CHK_QMIN_RANGE"; write(unit, Afmt) adjustl(param_name), adjustl(param_array(1)%value), adjustl(param_array(2)%value) - end if - write(param_name, Afmt) "MU2KG"; write(param_value, Rfmt) param%MU2KG; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "TU2S"; write(param_value, Rfmt) param%TU2S ; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "DU2M"; write(param_value, Rfmt) param%DU2M; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "RHILL_PRESENT"; write(param_value, Lfmt) param%lrhill_present; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "EXTRA_FORCE"; write(param_value, Lfmt) param%lextra_force; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "BIG_DISCARD"; write(param_value, Lfmt) param%lbig_discard; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "CHK_CLOSE"; write(param_value, Lfmt) param%lclose; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "ENERGY"; write(param_value, Lfmt) param%lenergy; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "GR"; write(param_value, Lfmt) param%lgr; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "ROTATION"; write(param_value, Lfmt) param%lrotation; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - write(param_name, Afmt) "TIDES"; write(param_value, Lfmt) param%ltides; write(unit, Afmt) adjustl(param_name), adjustl(param_value) - iostat = 0 - iomsg = "UDIO not implemented" - end associate - - return - end subroutine io_param_writer - - - module subroutine io_dump_param(self, param_file_name) - !! author: David A. Minton - !! - !! Dump integration parameters to file - !! - !! Adapted from David E. Kaufmann's Swifter routine io_dump_param.f90 - !! Adapted from Martin Duncan's Swift routine io_dump_param.f - implicit none - ! Arguments - 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) - ! Internals - integer(I4B), parameter :: LUN = 7 !! Unit number of output file - integer(I4B) :: ierr !! Error code - character(STRMAX) :: error_message !! Error message in UDIO procedure - - open(unit = LUN, file = param_file_name, status='replace', form = 'FORMATTED', iostat =ierr) - if (ierr /=0) then - write(*,*) 'Swiftest error.' - write(*,*) ' Could not open dump file: ',trim(adjustl(param_file_name)) - call util_exit(FAILURE) - end if - - !! todo: Currently this procedure does not work in user-defined derived-type input mode - !! due to compiler incompatabilities - !write(LUN,'(DT)') param - call self%writer(LUN, iotype = "none", v_list = [0], iostat = ierr, iomsg = error_message) - if (ierr /= 0) then - write(*,*) trim(adjustl(error_message)) - call util_exit(FAILURE) - end if - close(LUN) - - return - end subroutine io_dump_param - - - module subroutine io_dump_swiftest(self, param, msg) - !! author: David A. Minton - !! - !! Dump massive body data to files - !! - !! Adapted from David E. Kaufmann's Swifter routine: io_dump_pl.f90 and io_dump_tp.f90 - !! Adapted from Hal Levison's Swift routine io_dump_pl.f and io_dump_tp.f - implicit none - ! Arguments - class(swiftest_base), intent(inout) :: self !! Swiftest base object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - character(*), optional, intent(in) :: msg !! Message to display with dump operation - ! Internals - integer(I4B) :: ierr !! Error code - integer(I4B),parameter :: LUN = 7 !! Unit number for dump file - integer(I4B) :: iu = LUN - character(len=:), allocatable :: dump_file_name - - select type(self) - class is(swiftest_cb) - dump_file_name = trim(adjustl(param%incbfile)) - class is (swiftest_pl) - dump_file_name = trim(adjustl(param%inplfile)) - class is (swiftest_tp) - dump_file_name = trim(adjustl(param%intpfile)) - end select - open(unit = iu, file = dump_file_name, form = "UNFORMATTED", status = 'replace', iostat = ierr) - if (ierr /= 0) then - write(*, *) "Swiftest error:" - write(*, *) " Unable to open binary dump file " // dump_file_name - call util_exit(FAILURE) - end if - call self%write_frame(iu, param) - close(LUN) - - return - end subroutine io_dump_swiftest - - - module subroutine io_dump_system(self, param, msg) - !! author: David A. Minton - !! - !! Dumps the state of the system to files in case the simulation is interrupted. - !! As a safety mechanism, there are two dump files that are written in alternating order - !! so that if a dump file gets corrupted during writing, the user can restart from the older one. - implicit none - ! Arguments - class(swiftest_nbody_system), intent(inout) :: self !! Swiftest system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters - character(*), optional, intent(in) :: msg !! Message to display with dump operation - ! Internals - class(swiftest_parameters), allocatable :: dump_param !! Local parameters variable used to parameters change input file names - !! to dump file-specific values without changing the user-defined values - integer(I4B), save :: idx = 1 !! Index of current dump file. Output flips between 2 files for extra security - !! in case the program halts during writing - character(len=:), allocatable :: param_file_name - real(DP) :: tfrac - - allocate(dump_param, source=param) - param_file_name = trim(adjustl(DUMP_PARAM_FILE(idx))) - dump_param%incbfile = trim(adjustl(DUMP_CB_FILE(idx))) - dump_param%inplfile = trim(adjustl(DUMP_PL_FILE(idx))) - dump_param%intpfile = trim(adjustl(DUMP_TP_FILE(idx))) - dump_param%out_form = XV - dump_param%out_stat = 'APPEND' - dump_param%T0 = param%t - call dump_param%dump(param_file_name) - - call self%cb%dump(dump_param) - if (self%pl%nbody > 0) call self%pl%dump(dump_param) - if (self%tp%nbody > 0) call self%tp%dump(dump_param) - - idx = idx + 1 - if (idx > NDUMPFILES) idx = 1 - - ! Print the status message (format code passed in from main driver) - tfrac = (param%t - param%t0) / (param%tstop - param%t0) - write(*,msg) param%t, tfrac, self%pl%nbody, self%tp%nbody - - return - end subroutine io_dump_system - - - module function io_get_args(integrator, param_file_name) result(ierr) - !! author: David A. Minton - !! - !! Reads in the name of the parameter file from command line arguments. - implicit none - ! Arguments - integer(I4B) :: integrator !! Symbolic code of the requested integrator - character(len=:), allocatable :: param_file_name !! Name of the input parameters file - ! Result - integer(I4B) :: ierr !! I/O error code - ! Internals - character(len=STRMAX) :: arg1, arg2 - integer :: narg,ierr_arg1, ierr_arg2 - character(len=*),parameter :: linefmt = '(A)' + ! Calculate the inverse speed of light in the system units + self%inv_c2 = einsteinC * self%TU2S / self%DU2M + self%inv_c2 = (self%inv_c2)**(-2) - ierr = -1 ! Default is to fail - narg = command_argument_count() ! - if (narg == 2) then - call get_command_argument(1, arg1, status = ierr_arg1) - call get_command_argument(2, arg2, status = ierr_arg2) - if ((ierr_arg1 == 0) .and. (ierr_arg2 == 0)) then - ierr = 0 - call io_toupper(arg1) - select case(arg1) - case('BS') - integrator = BS - case('HELIO') - integrator = HELIO - case('RA15') - integrator = RA15 - case('TU4') - integrator = TU4 - case('WHM') - integrator = WHM - case('RMVS') - integrator = RMVS - case('SYMBA') - integrator = SYMBA - case('RINGMOONS') - integrator = RINGMOONS - case default - integrator = UNKNOWN_INTEGRATOR - write(*,*) trim(adjustl(arg1)) // ' is not a valid integrator.' - ierr = -1 - end select - param_file_name = trim(adjustl(arg2)) - end if - else - call get_command_argument(1, arg1, status = ierr_arg1) - if (ierr_arg1 == 0) then - if (arg1 == '-v' .or. arg1 == '--version') then - call util_version() - else if (arg1 == '-h' .or. arg1 == '--help') then - call util_exit(HELP) + associate(integrator => v_list(1)) + if (integrator == RMVS) then + if (.not.self%lclose) then + write(iomsg,*) 'This integrator requires CHK_CLOSE to be enabled.' + iostat = -1 + return end if end if - end if - if (ierr /= 0) call util_exit(USAGE) + + ! Determine if the GR flag is set correctly for this integrator + select case(integrator) + case(WHM, RMVS, HELIO, SYMBA) + write(*,*) "GR = ", self%lgr + case default + if (self%lgr) write(iomsg, *) 'GR is not yet implemented for this integrator. This parameter will be ignored.' + self%lgr = .false. + end select + end associate - return - end function io_get_args + iostat = 0 + + return + end subroutine io_param_reader - module function io_get_token(buffer, ifirst, ilast, ierr) result(token) + module subroutine io_param_writer(self, unit, iotype, v_list, iostat, iomsg) !! author: David A. Minton !! - !! Retrieves a character token from an input string. Here a token is defined as any set of contiguous non-blank characters not - !! beginning with or containing "!". If "!" is present, any remaining part of the buffer including the "!" is ignored + !! Dump integration parameters to file !! - !! Adapted from David E. Kaufmann's Swifter routine io_get_token.f90 + !! Adapted from David E. Kaufmann's Swifter routine io_dump_param.f90 + !! Adapted from Martin Duncan's Swift routine io_dump_param.f implicit none ! Arguments - 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 - ! Result - character(len=:), allocatable :: token !! Returned token string + class(swiftest_parameters),intent(in) :: self !! Collection of parameters + integer, intent(in) :: unit !! File unit number + character(len=*), intent(in) :: iotype !! Dummy argument passed to the input/output procedure contains the text from the char-literal-constant, prefixed with DT. + !! If you do not include a char-literal-constant, the iotype argument contains only DT. + integer, intent(in) :: v_list(:) !! Not used in this procedure + integer, intent(out) :: iostat !! IO status code + character(len=*), intent(inout) :: iomsg !! Message to pass if iostat /= 0 ! Internals - integer(I4B) :: i,ilength - - ilength = len(buffer) - - if (ifirst > ilength) then - ilast = ifirst - ierr = -1 !! Bad input - token = '' - return - end if - do i = ifirst, ilength - if (buffer(i:i) /= ' ') exit - end do - if ((i > ilength) .or. (buffer(i:i) == '!')) then - ifirst = i - ilast = i - ierr = -2 !! No valid token - token = '' - return - end if - ifirst = i - do i = ifirst, ilength - if ((buffer(i:i) == ' ') .or. (buffer(i:i) == '!')) exit - end do - ilast = i - 1 - ierr = 0 - - token = buffer(ifirst:ilast) + character(*),parameter :: Ifmt = '(I0)' !! Format label for integer values + character(*),parameter :: Rfmt = '(ES25.17)' !! Format label for real values + character(*),parameter :: Rarrfmt = '(3(ES25.17,1X))' !! Format label for real values + character(*),parameter :: Lfmt = '(L1)' !! Format label for logical values + character(len=*), parameter :: Afmt = '(A25,1X,64(:,A25,1X))' + character(256) :: param_name, param_value + type character_array + character(25) :: value + end type character_array + type(character_array), dimension(:), allocatable :: param_array + integer(I4B) :: i + + associate(param => self) + write(param_name, Afmt) "T0"; write(param_value,Rfmt) param%t0; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "TSTOP"; write(param_value, Rfmt) param%tstop; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "DT"; write(param_value, Rfmt) param%dt; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "PL_IN"; write(param_value, Afmt) trim(adjustl(param%inplfile)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "TP_in"; write(param_value, Afmt) trim(adjustl(param%intpfile)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "IN_TYPE"; write(param_value, Afmt) trim(adjustl(param%in_type)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + if (param%istep_out > 0) then + write(param_name, Afmt) "ISTEP_OUT"; write(param_value, Ifmt) param%istep_out; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "BIN_OUT"; write(param_value, Afmt) trim(adjustl(param%outfile)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "OUT_TYPE"; write(param_value, Afmt) trim(adjustl(param%out_type)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "OUT_FORM"; write(param_value, Afmt) trim(adjustl(param%out_form)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "OUT_STAT"; write(param_value, Afmt) "APPEND"; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + end if + write(param_name, Afmt) "ENC_OUT"; write(param_value, Afmt) trim(adjustl(param%enc_out)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + if (param%istep_dump > 0) then + write(param_name, Afmt) "ISTEP_DUMP"; write(param_value, Ifmt) param%istep_dump; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + end if + write(param_name, Afmt) "CHK_RMIN"; write(param_value, Rfmt) param%rmin; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "CHK_RMAX"; write(param_value, Rfmt) param%rmax; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "CHK_EJECT"; write(param_value, Rfmt) param%rmaxu; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "CHK_QMIN"; write(param_value, Rfmt) param%qmin; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + if (param%qmin >= 0.0_DP) then + write(param_name, Afmt) "CHK_QMIN_COORD"; write(param_value, Afmt) trim(adjustl(param%qmin_coord)); write(unit, Afmt) adjustl(param_name), adjustl(param_value) + allocate(param_array(2)) + write(param_array(1)%value, Rfmt) param%qmin_alo + write(param_array(2)%value, Rfmt) param%qmin_ahi + write(param_name, Afmt) "CHK_QMIN_RANGE"; write(unit, Afmt) adjustl(param_name), adjustl(param_array(1)%value), adjustl(param_array(2)%value) + end if + write(param_name, Afmt) "MU2KG"; write(param_value, Rfmt) param%MU2KG; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "TU2S"; write(param_value, Rfmt) param%TU2S ; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "DU2M"; write(param_value, Rfmt) param%DU2M; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "RHILL_PRESENT"; write(param_value, Lfmt) param%lrhill_present; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "EXTRA_FORCE"; write(param_value, Lfmt) param%lextra_force; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "BIG_DISCARD"; write(param_value, Lfmt) param%lbig_discard; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "CHK_CLOSE"; write(param_value, Lfmt) param%lclose; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "ENERGY"; write(param_value, Lfmt) param%lenergy; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "GR"; write(param_value, Lfmt) param%lgr; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "ROTATION"; write(param_value, Lfmt) param%lrotation; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + write(param_name, Afmt) "TIDES"; write(param_value, Lfmt) param%ltides; write(unit, Afmt) adjustl(param_name), adjustl(param_value) + iostat = 0 + iomsg = "UDIO not implemented" + end associate return - end function io_get_token + end subroutine io_param_writer module subroutine io_read_body_in(self, param) @@ -730,50 +730,9 @@ module subroutine io_read_cb_in(self, param) end subroutine io_read_cb_in - module subroutine io_read_param_in(self, param_file_name) - !! author: David A. Minton - !! - !! Read in parameters for the integration - !! - !! Adapted from David E. Kaufmann's Swifter routine io_init_param.f90 - !! Adapted from Martin Duncan's Swift routine io_init_param.f - implicit none - ! Arguments - 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) - ! Internals - integer(I4B), parameter :: LUN = 7 !! Unit number of input file - integer(I4B) :: ierr = 0 !! Input error code - character(STRMAX) :: error_message !! Error message in UDIO procedure - - ! Read in name of parameter file - write(*, *) 'Parameter input file is ', trim(adjustl(param_file_name)) - write(*, *) ' ' - 100 format(A) - open(unit = LUN, file = param_file_name, status = 'old', iostat = ierr) - if (ierr /= 0) then - write(*,*) 'Swiftest error: ', ierr - write(*,*) ' Unable to open file ',trim(adjustl(param_file_name)) - call util_exit(FAILURE) - end if - - !! todo: Currently this procedure does not work in user-defined derived-type input mode - !! as the newline characters are ignored in the input file when compiled in ifort. - - !read(LUN,'(DT)', iostat= ierr, iomsg = error_message) param - call self%reader(LUN, iotype= "none", v_list = [self%integrator], iostat = ierr, iomsg = error_message) - if (ierr /= 0) then - write(*,*) 'Swiftest error reading ', trim(adjustl(param_file_name)) - write(*,*) ierr,trim(adjustl(error_message)) - call util_exit(FAILURE) - end if - - return - end subroutine io_read_param_in - function io_read_encounter(t, name1, name2, mass1, mass2, radius1, radius2, & - xh1, xh2, vh1, vh2, enc_out, out_type) result(ierr) + xh1, xh2, vh1, vh2, enc_out, out_type) result(ierr) !! author: David A. Minton !! !! Read close encounter data from input binary files @@ -807,7 +766,7 @@ function io_read_encounter(t, name1, name2, mass1, mass2, radius1, radius2, & close(unit = iu, iostat = ierr) return end if - + read(iu, iostat = ierr) name1, xh1(1), xh1(2), xh1(3), vh1(1), vh1(2), vh1(3), mass1, radius1 if (ierr /= 0) then close(unit = iu, iostat = ierr) @@ -931,7 +890,7 @@ module subroutine io_read_frame_cb(self, iu, param, form, ierr) return end subroutine io_read_frame_cb - + module subroutine io_read_frame_system(self, iu, param, form, ierr) !! author: The Purdue Swiftest Team - David A. Minton, Carlisle A. Wishard, Jennifer L.L. Pouplin, and Jacob R. Elliott !! @@ -1009,6 +968,47 @@ function io_read_hdr(iu, t, npl, ntp, out_form, out_type) result(ierr) return end function io_read_hdr + module subroutine io_read_param_in(self, param_file_name) + !! author: David A. Minton + !! + !! Read in parameters for the integration + !! + !! Adapted from David E. Kaufmann's Swifter routine io_init_param.f90 + !! Adapted from Martin Duncan's Swift routine io_init_param.f + implicit none + ! Arguments + 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) + ! Internals + integer(I4B), parameter :: LUN = 7 !! Unit number of input file + integer(I4B) :: ierr = 0 !! Input error code + character(STRMAX) :: error_message !! Error message in UDIO procedure + + ! Read in name of parameter file + write(*, *) 'Parameter input file is ', trim(adjustl(param_file_name)) + write(*, *) ' ' + 100 format(A) + open(unit = LUN, file = param_file_name, status = 'old', iostat = ierr) + if (ierr /= 0) then + write(*,*) 'Swiftest error: ', ierr + write(*,*) ' Unable to open file ',trim(adjustl(param_file_name)) + call util_exit(FAILURE) + end if + + !! todo: Currently this procedure does not work in user-defined derived-type input mode + !! as the newline characters are ignored in the input file when compiled in ifort. + + !read(LUN,'(DT)', iostat= ierr, iomsg = error_message) param + call self%reader(LUN, iotype= "none", v_list = [self%integrator], iostat = ierr, iomsg = error_message) + if (ierr /= 0) then + write(*,*) 'Swiftest error reading ', trim(adjustl(param_file_name)) + write(*,*) ierr,trim(adjustl(error_message)) + call util_exit(FAILURE) + end if + + return + end subroutine io_read_param_in + module subroutine io_toupper(string) !! author: David A. Minton diff --git a/src/modules/symba_classes.f90 b/src/modules/symba_classes.f90 index c5aba1a7f..f920fff87 100644 --- a/src/modules/symba_classes.f90 +++ b/src/modules/symba_classes.f90 @@ -537,9 +537,9 @@ end subroutine symba_util_peri_pl module subroutine symba_util_rearray_pl(self, system, param) implicit none - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(symba_pl), intent(inout) :: self !! SyMBA massive body object + class(symba_nbody_system), intent(inout) :: system !! SyMBA nbody system object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters with SyMBA additions end subroutine symba_util_rearray_pl end interface diff --git a/src/symba/symba_discard.f90 b/src/symba/symba_discard.f90 index 33fe47354..6ab835e36 100644 --- a/src/symba/symba_discard.f90 +++ b/src/symba/symba_discard.f90 @@ -310,7 +310,7 @@ module subroutine symba_discard_pl(self, system, param) if (any(pl%ldiscard(:))) then call symba_discard_nonplpl_conservation(self, system, param) - !call pl%rearray(self, system, param) + call pl%rearray(system, param) end if end associate diff --git a/src/symba/symba_fragmentation.f90 b/src/symba/symba_fragmentation.f90 index cafaacfd7..f8afffb85 100644 --- a/src/symba/symba_fragmentation.f90 +++ b/src/symba/symba_fragmentation.f90 @@ -97,6 +97,8 @@ module function symba_fragmentation_casemerge(system, param, family, x, v, mass, ibiggest = maxloc(pl%Gmass(family(:)), dim=1) plnew%id(1) = pl%id(family(ibiggest)) plnew%status(1) = ACTIVE + plnew%lcollision = .false. + plnew%ldiscard = .false. plnew%xb(:,1) = xcom(:) plnew%vb(:,1) = vcom(:) plnew%xh(:,1) = xcom(:) - cb%xb(:) diff --git a/src/symba/symba_util.f90 b/src/symba/symba_util.f90 index c0276291a..98c8889d8 100644 --- a/src/symba/symba_util.f90 +++ b/src/symba/symba_util.f90 @@ -375,17 +375,37 @@ module subroutine symba_util_rearray_pl(self, system, param) !! Clean up the massive body structures to remove discarded bodies and add new bodies implicit none ! Arguments - class(symba_pl), intent(inout) :: self !! SyMBA massive body object - class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object - class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + class(symba_pl), intent(inout) :: self !! SyMBA massive body object + class(symba_nbody_system), intent(inout) :: system !! Swiftest nbody system object + class(symba_parameters), intent(in) :: param !! Current run configuration parameters + ! Internals + class(symba_pl), allocatable :: pl_discards !! The discarded body list. + + associate(pl => self, mergeadd_list => system%mergeadd_list) + allocate(pl_discards, mold=pl) + ! Remove the discards + call pl%spill(pl_discards, lspill_list=(pl%ldiscard(:) .or. pl%status(:) == INACTIVE), ldestructive=.true.) + + ! Add in any new bodies + call pl%append(mergeadd_list) + + ! If there are still bodies in the system, sort by mass in descending order and re-index + if (pl%nbody > 0) then + call pl%sort("mass", ascending=.false.) + pl%lmtiny(:) = pl%Gmass(:) > param%MTINY + pl%nplm = count(pl%lmtiny(:)) + call pl%eucl_index() + end if - ! First + ! Destroy the discarded body list, since we already have what we need in the mergesub_list + call pl_discards%setup(0,param) + deallocate(pl_discards) + end associate return end subroutine symba_util_rearray_pl - module subroutine symba_util_resize_arr_info(arr, nnew) !! author: David A. Minton !! diff --git a/src/util/util_spill.f90 b/src/util/util_spill.f90 index 0cef49194..9acc6ae93 100644 --- a/src/util/util_spill.f90 +++ b/src/util/util_spill.f90 @@ -163,6 +163,7 @@ module subroutine util_spill_body(self, discards, lspill_list, ldestructive) call util_spill(keeps%name, discards%name, lspill_list, ldestructive) call util_spill(keeps%status, discards%status, lspill_list, ldestructive) call util_spill(keeps%lmask, discards%lmask, lspill_list, ldestructive) + call util_spill(keeps%ldiscard, discards%ldiscard, lspill_list, ldestructive) call util_spill(keeps%mu, discards%mu, lspill_list, ldestructive) call util_spill(keeps%xh, discards%xh, lspill_list, ldestructive) call util_spill(keeps%vh, discards%vh, lspill_list, ldestructive) From fb21ff7e17451588f65bbdcfbfbbba96591b1690 Mon Sep 17 00:00:00 2001 From: David A Minton Date: Wed, 4 Aug 2021 20:36:45 -0400 Subject: [PATCH 42/42] Added energy and momentum report back in --- src/io/io.f90 | 86 ++++++++++++++++++ src/modules/swiftest_classes.f90 | 62 ++++++++++--- src/obl/obl.f90 | 40 +++++++++ src/util/util_get_energy_momentum.f90 | 121 ++++++++++++++++++++++++++ 4 files changed, 299 insertions(+), 10 deletions(-) create mode 100644 src/util/util_get_energy_momentum.f90 diff --git a/src/io/io.f90 b/src/io/io.f90 index 145752836..e159d019d 100644 --- a/src/io/io.f90 +++ b/src/io/io.f90 @@ -2,6 +2,92 @@ use swiftest contains + module subroutine io_conservation_report(self, param, lterminal) + !! author: The Purdue Swiftest Team - David A. Minton, Carlisle A. Wishard, Jennifer L.L. Pouplin, and Jacob R. Elliott + !! + !! Reports the current state of energy, mass, and angular momentum conservation in a run + implicit none + ! Arguments + 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 + ! Internals + real(DP), dimension(NDIM) :: Ltot_now, Lorbit_now, Lspin_now + real(DP), dimension(NDIM), save :: Ltot_last, Lorbit_last, Lspin_last + real(DP), save :: ke_orbit_last, ke_spin_last, pe_last, Eorbit_last + real(DP) :: ke_orbit_now, ke_spin_now, pe_now, Eorbit_now + real(DP) :: Eorbit_error, Etotal_error, Ecoll_error + real(DP) :: Mtot_now, Merror + real(DP) :: Lmag_now, Lerror + character(len=*), parameter :: EGYFMT = '(ES23.16,10(",",ES23.16,:))' ! Format code for all simulation output + character(len=*), parameter :: EGYHEADER = '("t,Eorbit,Ecollisions,Lx,Ly,Lz,Mtot")' + integer(I4B), parameter :: EGYIU = 72 + character(len=*), parameter :: EGYTERMFMT = '(" DL/L0 = ", ES12.5 & + "; DEcollisions/|E0| = ", ES12.5, & + "; D(Eorbit+Ecollisions)/|E0| = ", ES12.5, & + "; DM/M0 = ", ES12.5)' + + associate(system => self, pl => self%pl, cb => self%cb, npl => self%pl%nbody, Ecollisions => self%Ecollisions, Lescape => self%Lescape, Mescape => self%Mescape, & + Euntracked => self%Euntracked, Eorbit_orig => param%Eorbit_orig, Mtot_orig => param%Mtot_orig, & + Ltot_orig => param%Ltot_orig(:), Lmag_orig => param%Lmag_orig, Lorbit_orig => param%Lorbit_orig(:), Lspin_orig => param%Lspin_orig(:), & + lfirst => param%lfirstenergy) + if (lfirst) then + if (param%out_stat == "OLD") then + open(unit = EGYIU, file = ENERGY_FILE, form = "formatted", status = "old", action = "write", position = "append") + else + open(unit = EGYIU, file = ENERGY_FILE, form = "formatted", status = "replace", action = "write") + write(EGYIU,EGYHEADER) + end if + end if + call system%get_energy_and_momentum(param, ke_orbit_now, ke_spin_now, pe_now, Lorbit_now, Lspin_now) + Eorbit_now = ke_orbit_now + ke_spin_now + pe_now + Ltot_now(:) = Lorbit_now(:) + Lspin_now(:) + Lescape(:) + Mtot_now = cb%mass + sum(pl%mass(1:npl)) + system%Mescape + if (lfirst) then + Eorbit_orig = Eorbit_now + Mtot_orig = Mtot_now + Lorbit_orig(:) = Lorbit_now(:) + Lspin_orig(:) = Lspin_now(:) + Ltot_orig(:) = Ltot_now(:) + Lmag_orig = norm2(Ltot_orig(:)) + lfirst = .false. + end if + + write(EGYIU,EGYFMT) param%t, Eorbit_now, Ecollisions, Ltot_now, Mtot_now + flush(EGYIU) + if (.not.lfirst .and. lterminal) then + Lmag_now = norm2(Ltot_now) + Lerror = norm2(Ltot_now - Ltot_orig) / Lmag_orig + Eorbit_error = (Eorbit_now - Eorbit_orig) / abs(Eorbit_orig) + Ecoll_error = Ecollisions / abs(Eorbit_orig) + Etotal_error = (Eorbit_now - Ecollisions - Eorbit_orig - Euntracked) / abs(Eorbit_orig) + Merror = (Mtot_now - Mtot_orig) / Mtot_orig + write(*, egytermfmt) Lerror, Ecoll_error, Etotal_error, Merror + if (Ecoll_error > 0.0_DP) then + write(*,*) 'Something has gone wrong! Collisional energy should not be positive!' + write(*,*) 'dke_orbit: ',(ke_orbit_now - ke_orbit_last) / abs(Eorbit_orig) + write(*,*) 'dke_spin : ',(ke_spin_now - ke_spin_last) / abs(Eorbit_orig) + write(*,*) 'dpe : ',(pe_now - pe_last) / abs(Eorbit_orig) + write(*,*) + end if + if (Lerror > 1e-6) then + write(*,*) 'Something has gone wrong! Angular momentum is too high!' + write(*,*) 'Lerror: ', Lerror + end if + end if + ke_orbit_last = ke_orbit_now + ke_spin_last = ke_spin_now + pe_last = pe_now + Eorbit_last = Eorbit_now + Lorbit_last(:) = Lorbit_now(:) + Lspin_last(:) = Lspin_now(:) + Ltot_last(:) = Ltot_now(:) + end associate + return + + end subroutine io_conservation_report + + module subroutine io_dump_param(self, param_file_name) !! author: David A. Minton !! diff --git a/src/modules/swiftest_classes.f90 b/src/modules/swiftest_classes.f90 index 74add9081..dcff0f6d8 100644 --- a/src/modules/swiftest_classes.f90 +++ b/src/modules/swiftest_classes.f90 @@ -45,8 +45,9 @@ module swiftest_classes 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 + character(STRMAX) :: ennergy_out = "" !! Name of output energy and momentum report file - !Logical flags to turn on or off various features of the code + ! 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 @@ -56,6 +57,16 @@ module swiftest_classes 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) :: Eorbit_orig = 0.0_DP !! Initial orbital energy + real(DP) :: Mtot_orig = 0.0_DP !! Initial system mass + real(DP) :: Lmag_orig = 0.0_DP !! Initial total angular momentum magnitude + real(DP), dimension(NDIM) :: Ltot_orig = 0.0_DP !! Initial total angular momentum vector + real(DP), dimension(NDIM) :: Lorbit_orig = 0.0_DP !! Initial orbital angular momentum + real(DP), dimension(NDIM) :: Lspin_orig = 0.0_DP !! Initial spin angular momentum vector + logical :: lfirstenergy = .true. !! This is the first time computing energe + logical :: lfirstkick = .true. !! Initiate the first kick in a symplectic step + ! Future features not implemented or in development logical :: lgr = .false. !! Turn on GR logical :: lyarkovsky = .false. !! Turn on Yarkovsky effect @@ -259,7 +270,7 @@ module swiftest_classes 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 - real(DP) :: Gmtot = 0.0_DP !! Total system mass - used for barycentric coordinate conversion + real(DP) :: Gmtot = 0.0_DP !! Total system mass - used for barycentric coordinate conversion real(DP) :: ke = 0.0_DP !! System kinetic energy real(DP) :: pe = 0.0_DP !! System potential energy real(DP) :: te = 0.0_DP !! System total energy @@ -276,14 +287,16 @@ module swiftest_classes procedure(abstract_step_system), deferred :: step ! Concrete classes that are common to the basic integrator (only test particles considered for discard) - procedure :: discard => discard_system !! Perform a discard step on the system - procedure :: dump => io_dump_system !! Dump the state of the system to a file - procedure :: read_frame => io_read_frame_system !! Read in a frame of input data from file - procedure :: write_discard => io_write_discard !! Write out information about discarded test particles - procedure :: write_frame => io_write_frame_system !! Append a frame of output data to file - procedure :: initialize => setup_initialize_system !! Initialize the 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 => util_set_msys !! Sets the value of msys from the masses of system bodies. + procedure :: discard => discard_system !! Perform a discard step on the system + procedure :: conservation_report => io_conservation_report !! Compute energy and momentum and print out the change with time + procedure :: dump => io_dump_system !! Dump the state of the system to a file + procedure :: read_frame => io_read_frame_system !! Read in a frame of input data from file + procedure :: write_discard => io_write_discard !! Write out information about discarded test particles + procedure :: write_frame => io_write_frame_system !! Append a frame of output data to file + procedure :: initialize => setup_initialize_system !! Initialize the 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 => util_set_msys !! Sets the value of msys from the masses of system bodies. + procedure :: get_energy_and_momentum => util_get_energy_momentum_system !! Calculates the total system energy and momentum end type swiftest_nbody_system type :: swiftest_encounter @@ -487,6 +500,13 @@ module pure subroutine gr_vh2pv_body(self, param) class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters end subroutine gr_vh2pv_body + module subroutine 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 + end subroutine io_conservation_report + module subroutine io_dump_param(self, param_file_name) implicit none class(swiftest_parameters),intent(in) :: self !! Output collection of parameters @@ -662,6 +682,17 @@ module subroutine obl_acc_tp(self, system) class(swiftest_nbody_system), intent(inout) :: system !! Swiftest nbody system object end subroutine obl_acc_tp + module subroutine obl_pot(npl, Mcb, Mpl, j2rp2, j4rp4, xh, irh, oblpot) + implicit none + integer(I4B), intent(in) :: npl + real(DP), intent(in) :: Mcb + real(DP), dimension(:), intent(in) :: Mpl + real(DP), intent(in) :: j2rp2, j4rp4 + real(DP), dimension(:), intent(in) :: irh + real(DP), dimension(:, :), intent(in) :: xh + real(DP), intent(out) :: oblpot + end subroutine obl_pot + module subroutine orbel_el2xv_vec(self, cb) implicit none class(swiftest_body), intent(inout) :: self !! Swiftest body object @@ -983,6 +1014,17 @@ module subroutine util_resize_tp(self, nnew) integer(I4B), intent(in) :: nnew !! New size neded end subroutine util_resize_tp + module subroutine util_get_energy_momentum_system(self, param, ke_orbit, ke_spin, pe, Lorbit, Lspin) + implicit none + class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + real(DP), intent(out) :: ke_orbit !! Orbital kinetic energy + real(DP), intent(out) :: ke_spin !! Spin kinetic energy + real(DP), intent(out) :: pe !! Potential energy + real(DP), dimension(:), intent(out) :: Lorbit !! Orbital angular momentum + real(DP), dimension(:), intent(out) :: Lspin !! Spin angular momentum + end subroutine util_get_energy_momentum_system + module subroutine util_set_beg_end_pl(self, xbeg, xend, vbeg) implicit none class(swiftest_pl), intent(inout) :: self !! Swiftest massive body object diff --git a/src/obl/obl.f90 b/src/obl/obl.f90 index 91b20b62b..035a54b18 100644 --- a/src/obl/obl.f90 +++ b/src/obl/obl.f90 @@ -106,5 +106,45 @@ module subroutine obl_acc_tp(self, system) end subroutine obl_acc_tp + module subroutine obl_pot(npl, Mcb, Mpl, j2rp2, j4rp4, xh, irh, oblpot) + !! author: David A. Minton + !! + !! Compute the contribution to the total gravitational potential due solely to the oblateness of the central 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. + !! + !! Adapted from David E. Kaufmann's Swifter routine: obl_pot.f90 + !! Adapted from Hal Levison's Swift routine obl_pot.f + implicit none + ! Arguments + integer(I4B), intent(in) :: npl + real(DP), intent(in) :: Mcb + real(DP), dimension(:), intent(in) :: Mpl + real(DP), intent(in) :: j2rp2, j4rp4 + real(DP), dimension(:), intent(in) :: irh + real(DP), dimension(:, :), intent(in) :: xh + real(DP), intent(out) :: oblpot + + ! Internals + integer(I4B) :: i + real(DP) :: rinv2, t0, t1, t2, t3, p2, p4, mu + + oblpot = 0.0_DP + mu = Mcb + do i = 1, npl + rinv2 = irh(i)**2 + t0 = mu * Mpl(i) * rinv2 * irh(i) + t1 = j2rp2 + t2 = xh(3, i) * xh(3, i) * rinv2 + t3 = j4rp4 * rinv2 + p2 = 0.5_DP * (3 * t2 - 1.0_DP) + p4 = 0.125_DP * ((35 * t2 - 30.0_DP) * t2 + 3.0_DP) + oblpot = oblpot + t0 * (t1 * p2 + t3 * p4) + end do + + return + end subroutine obl_pot + end submodule s_obl diff --git a/src/util/util_get_energy_momentum.f90 b/src/util/util_get_energy_momentum.f90 new file mode 100644 index 000000000..69936e1b2 --- /dev/null +++ b/src/util/util_get_energy_momentum.f90 @@ -0,0 +1,121 @@ +submodule (swiftest_classes) s_util_get_energy_momentum + use swiftest +contains + module subroutine util_get_energy_momentum_system(self, param, ke_orbit, ke_spin, pe, Lorbit, Lspin) + !! author: David A. Minton + !! + !! Compute total system angular momentum vector and kinetic, potential and total system energy + !! + !! Adapted from David E. Kaufmann Swifter routine symba_energy_eucl.f90 + !! + !! Adapted from Martin Duncan's Swift routine anal_energy.f + implicit none + class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object + class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters + real(DP), intent(out) :: ke_orbit !! Orbital kinetic energy + real(DP), intent(out) :: ke_spin !! Spin kinetic energy + real(DP), intent(out) :: pe !! Potential energy + real(DP), dimension(:), intent(out) :: Lorbit !! Orbital angular momentum + real(DP), dimension(:), intent(out) :: Lspin !! Spin angular momentum + ! Internals + integer(I4B) :: i, j + integer(I8B) :: k + real(DP) :: rmag, v2, rot2, oblpot, hx, hy, hz, hsx, hsy, hsz + real(DP), dimension(self%pl%nbody) :: irh, kepl, kespinpl, pecb + real(DP), dimension(self%pl%nbody) :: Lplorbitx, Lplorbity, Lplorbitz + real(DP), dimension(self%pl%nbody) :: Lplspinx, Lplspiny, Lplspinz + real(DP), dimension(self%pl%nplpl) :: pepl + logical, dimension(self%pl%nplpl) :: lstatpl + logical, dimension(self%pl%nbody) :: lstatus + + Lorbit(:) = 0.0_DP + Lspin(:) = 0.0_DP + ke_orbit = 0.0_DP + ke_spin = 0.0_DP + associate(system => self, pl => self%pl, npl => self%pl%nbody, cb => self%cb) + kepl(:) = 0.0_DP + Lplorbitx(:) = 0.0_DP + Lplorbity(:) = 0.0_DP + Lplorbitz(:) = 0.0_DP + Lplspinx(:) = 0.0_DP + Lplspiny(:) = 0.0_DP + Lplspinz(:) = 0.0_DP + lstatus(1:npl) = pl%status(1:npl) /= INACTIVE + !!$omp simd private(v2, rot2, hx, hy, hz) + do i = 1, npl + v2 = dot_product(pl%vb(:,i), pl%vb(:,i)) + hx = pl%xb(2,i) * pl%vb(3,i) - pl%xb(3,i) * pl%vb(2,i) + hy = pl%xb(3,i) * pl%vb(1,i) - pl%xb(1,i) * pl%vb(3,i) + hz = pl%xb(1,i) * pl%vb(2,i) - pl%xb(2,i) * pl%vb(1,i) + + ! Angular momentum from orbit + Lplorbitx(i) = pl%mass(i) * hx + Lplorbity(i) = pl%mass(i) * hy + Lplorbitz(i) = pl%mass(i) * hz + + ! Kinetic energy from orbit and spin + kepl(i) = pl%mass(i) * v2 + end do + if (param%lrotation) then + do i = 1, npl + rot2 = dot_product(pl%rot(:,i), pl%rot(:,i)) + ! For simplicity, we always assume that the rotation pole is the 3rd principal axis + hsx = pl%Ip(3,i) * pl%radius(i)**2 * pl%rot(1,i) + hsy = pl%Ip(3,i) * pl%radius(i)**2 * pl%rot(2,i) + hsz = pl%Ip(3,i) * pl%radius(i)**2 * pl%rot(3,i) + + ! Angular momentum from spin + Lplspinx(i) = pl%mass(i) * hsx + Lplspiny(i) = pl%mass(i) * hsy + Lplspinz(i) = pl%mass(i) * hsz + kespinpl(i) = pl%mass(i) * pl%Ip(3, i) * pl%radius(i)**2 * rot2 + end do + else + kespinpl(:) = 0.0_DP + end if + + ! Do the central body potential energy component first + !$omp simd + do i = 1, npl + associate(px => pl%xh(1,i), py => pl%xh(2,i), pz => pl%xh(3,i)) + pecb(i) = -cb%mass * pl%mass(i) / sqrt(px**2 + py**2 + pz**2) + end associate + end do + + ! Do the potential energy between pairs of massive bodies + do k = 1, pl%nplpl + associate(ik => pl%k_plpl(1, k), jk => pl%k_plpl(2, k)) + pepl(k) = -pl%mass(ik) * pl%mass(jk) / norm2(pl%xb(:, jk) - pl%xb(:, ik)) + lstatpl(k) = (lstatus(ik) .and. lstatus(jk)) + end associate + end do + + ke_orbit = 0.5_DP * sum(kepl(1:npl), lstatus(:)) + if (param%lrotation) ke_spin = 0.5_DP * sum(kespinpl(1:npl), lstatus(:)) + + pe = sum(pepl(:), lstatpl(:)) + sum(pecb(2:npl), lstatus(2:npl)) + + ! Potential energy from the oblateness term + if (param%loblatecb) then + !$omp simd + do i = 1, npl + irh(i) = 1.0_DP / norm2(pl%xh(:,i)) + end do + call obl_pot(npl, cb%mass, pl%mass, cb%j2rp2, cb%j4rp4, pl%xh, irh, oblpot) + pe = pe + oblpot + end if + + Lorbit(1) = sum(Lplorbitx(1:npl), lstatus(1:npl)) + Lorbit(2) = sum(Lplorbity(1:npl), lstatus(1:npl)) + Lorbit(3) = sum(Lplorbitz(1:npl), lstatus(1:npl)) + + Lspin(1) = sum(Lplspinx(1:npl), lstatus(1:npl)) + Lspin(2) = sum(Lplspiny(1:npl), lstatus(1:npl)) + Lspin(3) = sum(Lplspinz(1:npl), lstatus(1:npl)) + + end associate + + return + end subroutine util_get_energy_momentum_system + +end submodule s_util_get_energy_momentum