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

Commit

Permalink
Created the structure needed to send spin equations into the adaptive…
Browse files Browse the repository at this point in the history
… RKF45 solver
  • Loading branch information
daminton committed Jul 13, 2021
1 parent 1181c9a commit d0126da
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@
" 1.17040422e-11])\n",
"Coordinates:\n",
" id int64 2\n",
" * time (d) (time (d)) float64 0.0 11.0 22.0 ... 3.63e+03 3.641e+03 3.652e+03</pre><div class='xr-wrap' hidden><div class='xr-header'><div class='xr-obj-type'>xarray.DataArray</div><div class='xr-array-name'>'rmag'</div><ul class='xr-dim-list'><li><span class='xr-has-index'>time (d)</span>: 333</li></ul></div><ul class='xr-sections'><li class='xr-section-item'><div class='xr-array-wrap'><input id='section-8749a769-0901-41f5-9ba4-019a50cd278c' class='xr-array-in' type='checkbox' checked><label for='section-8749a769-0901-41f5-9ba4-019a50cd278c' title='Show/hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-array-preview xr-preview'><span>0.0 0.0 0.0 0.0 0.0 ... 2.959e-11 2.323e-11 1.702e-11 1.17e-11</span></div><div class='xr-array-data'><pre>array([0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n",
" * time (d) (time (d)) float64 0.0 11.0 22.0 ... 3.63e+03 3.641e+03 3.652e+03</pre><div class='xr-wrap' hidden><div class='xr-header'><div class='xr-obj-type'>xarray.DataArray</div><div class='xr-array-name'>'rmag'</div><ul class='xr-dim-list'><li><span class='xr-has-index'>time (d)</span>: 333</li></ul></div><ul class='xr-sections'><li class='xr-section-item'><div class='xr-array-wrap'><input id='section-3692e8f7-8e63-4397-874d-ca335f0335ef' class='xr-array-in' type='checkbox' checked><label for='section-3692e8f7-8e63-4397-874d-ca335f0335ef' title='Show/hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-array-preview xr-preview'><span>0.0 0.0 0.0 0.0 0.0 ... 2.959e-11 2.323e-11 1.702e-11 1.17e-11</span></div><div class='xr-array-data'><pre>array([0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n",
" 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n",
" 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n",
" 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n",
Expand Down Expand Up @@ -662,7 +662,7 @@
" 2.44264806e-11, 3.07065663e-11, 3.63320360e-11, 4.07478190e-11,\n",
" 4.35128453e-11, 4.43475549e-11, 4.31649567e-11, 4.00801554e-11,\n",
" 3.53984592e-11, 2.95862328e-11, 2.32329074e-11, 1.70175537e-11,\n",
" 1.17040422e-11])</pre></div></div></li><li class='xr-section-item'><input id='section-1bceb514-f629-4b6a-871d-fc24a1a135d7' class='xr-section-summary-in' type='checkbox' checked><label for='section-1bceb514-f629-4b6a-871d-fc24a1a135d7' class='xr-section-summary' >Coordinates: <span>(2)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span>id</span></div><div class='xr-var-dims'>()</div><div class='xr-var-dtype'>int64</div><div class='xr-var-preview xr-preview'>2</div><input id='attrs-dc752801-1fdf-44a8-aeb0-eee157ccdc9d' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-dc752801-1fdf-44a8-aeb0-eee157ccdc9d' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-0038f928-da2d-4b40-95d1-abdab17c6512' class='xr-var-data-in' type='checkbox'><label for='data-0038f928-da2d-4b40-95d1-abdab17c6512' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array(2)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>time (d)</span></div><div class='xr-var-dims'>(time (d))</div><div class='xr-var-dtype'>float64</div><div class='xr-var-preview xr-preview'>0.0 11.0 ... 3.641e+03 3.652e+03</div><input id='attrs-0e4a8e9d-e44e-4dd5-a44c-e3bb7f765c03' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-0e4a8e9d-e44e-4dd5-a44c-e3bb7f765c03' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-5062c5ac-955c-45fe-9574-995273df53d6' class='xr-var-data-in' type='checkbox'><label for='data-5062c5ac-955c-45fe-9574-995273df53d6' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array([ 0., 11., 22., ..., 3630., 3641., 3652.])</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-1720088d-f5e3-4e21-95eb-a213002b5b0a' class='xr-section-summary-in' type='checkbox' disabled ><label for='section-1720088d-f5e3-4e21-95eb-a213002b5b0a' class='xr-section-summary' title='Expand/collapse section'>Attributes: <span>(0)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><dl class='xr-attrs'></dl></div></li></ul></div></div>"
" 1.17040422e-11])</pre></div></div></li><li class='xr-section-item'><input id='section-0774eb86-e07d-42e2-a849-c819e3e57bbf' class='xr-section-summary-in' type='checkbox' checked><label for='section-0774eb86-e07d-42e2-a849-c819e3e57bbf' class='xr-section-summary' >Coordinates: <span>(2)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span>id</span></div><div class='xr-var-dims'>()</div><div class='xr-var-dtype'>int64</div><div class='xr-var-preview xr-preview'>2</div><input id='attrs-cd565590-0ab9-465f-8b17-8b70177e0e8d' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-cd565590-0ab9-465f-8b17-8b70177e0e8d' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-817c1952-dcbb-4f45-8c25-97fe440b8671' class='xr-var-data-in' type='checkbox'><label for='data-817c1952-dcbb-4f45-8c25-97fe440b8671' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array(2)</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>time (d)</span></div><div class='xr-var-dims'>(time (d))</div><div class='xr-var-dtype'>float64</div><div class='xr-var-preview xr-preview'>0.0 11.0 ... 3.641e+03 3.652e+03</div><input id='attrs-07ccb926-0a7b-4274-bd2e-c44cf8b7f23b' class='xr-var-attrs-in' type='checkbox' disabled><label for='attrs-07ccb926-0a7b-4274-bd2e-c44cf8b7f23b' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-e81aec9a-1cd1-4af7-819e-223d5d283d94' class='xr-var-data-in' type='checkbox'><label for='data-e81aec9a-1cd1-4af7-819e-223d5d283d94' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'></dl></div><div class='xr-var-data'><pre>array([ 0., 11., 22., ..., 3630., 3641., 3652.])</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-fcfd1eae-6bea-400b-88cf-526cf12b1a38' class='xr-section-summary-in' type='checkbox' disabled ><label for='section-fcfd1eae-6bea-400b-88cf-526cf12b1a38' class='xr-section-summary' title='Expand/collapse section'>Attributes: <span>(0)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><dl class='xr-attrs'></dl></div></li></ul></div></div>"
],
"text/plain": [
"<xarray.DataArray 'rmag' (time (d): 333)>\n",
Expand Down
46 changes: 43 additions & 3 deletions src/modules/lambda_function.f90
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,19 @@ module lambda_function
procedure :: eval => lambda_eval_0_err
procedure, nopass :: lambda_init_0_err
end type

type, extends(lambda_obj) :: lambda_obj_tvar
!! Base class for an lambda function object. This object takes no additional arguments other than the dependent variable x, an array of real numbers
procedure(lambda0tvar), pointer, nopass :: lambdaptr_tvar => null()
contains
generic :: init => lambda_init_tvar
procedure :: evalt => lambda_eval_tvar
procedure, nopass :: lambda_init_tvar
end type
interface lambda_obj
module procedure lambda_init_0
module procedure lambda_init_0_err
module procedure lambda_init_tvar
end interface

abstract interface
Expand All @@ -158,21 +168,29 @@ function lambda0(x) result(y)
real(DP), dimension(:), intent(in) :: x
real(DP) :: y
end function

function lambda0err(x, lerr) result(y)
! Template for a 0 argument function that returns an error value
import DP
real(DP), dimension(:), intent(in) :: x
logical, intent(out) :: lerr
real(DP) :: y
end function

function lambda0tvar(x, t) result(y)
! Template for a 0 argument function that returns an error value
import DP
real(DP), dimension(:), intent(in) :: x
real(DP), intent(in) :: t
real(DP), dimension(:), allocatable :: y
end function
end interface

contains
type(lambda_obj) function lambda_init_0(lambda)
implicit none
! Arguments
procedure(lambda0) :: lambda

lambda_init_0%lambdaptr => lambda
return
end function lambda_init_0
Expand All @@ -186,6 +204,15 @@ type(lambda_obj_err) function lambda_init_0_err(lambda, lerr)
lambda_init_0_err%lerr = lerr
return
end function lambda_init_0_err

type(lambda_obj_tvar) function lambda_init_tvar(lambda, t)
implicit none
! Arguments
procedure(lambda0tvar) :: lambda
real(DP), intent(in) :: t
lambda_init_tvar%lambdaptr_tvar => lambda
return
end function lambda_init_tvar

function lambda_eval_0(self, x) result(y)
implicit none
Expand All @@ -194,7 +221,6 @@ function lambda_eval_0(self, x) result(y)
real(DP), dimension(:), intent(in) :: x
! Result
real(DP) :: y

if (associated(self%lambdaptr)) then
y = self%lambdaptr(x)
self%lastval = y
Expand All @@ -212,7 +238,6 @@ function lambda_eval_0_err(self, x) result(y)
real(DP), dimension(:), intent(in) :: x
! Result
real(DP) :: y

if (associated(self%lambdaptr_err)) then
y = self%lambdaptr_err(x, self%lerr)
self%lastval = y
Expand All @@ -223,6 +248,21 @@ function lambda_eval_0_err(self, x) result(y)
end if
end function lambda_eval_0_err

function lambda_eval_tvar(self, x, t) result(y)
implicit none
! Arguments
class(lambda_obj_tvar), intent(inout) :: self
real(DP), dimension(:), intent(in) :: x
real(DP), intent(in) :: t
! Result
real(DP), dimension(:), allocatable :: y
if (associated(self%lambdaptr_tvar)) then
y = self%lambdaptr_tvar(x,t)
else
error stop "Lambda function was not initialized"
end if
end function lambda_eval_tvar

subroutine lambda_destroy(self)
implicit none
type(lambda_obj) :: self
Expand Down
110 changes: 110 additions & 0 deletions src/tides/tides_spin_step.f90
Original file line number Diff line number Diff line change
@@ -1,15 +1,125 @@
submodule(swiftest_classes) s_tides_step_spin
use swiftest

type, extends(lambda_obj_tvar) :: tides_derivs_func
!! Base class for an lambda function object. This object takes no additional arguments other than the dependent variable x, an array of real numbers
procedure(tidederiv), pointer, nopass :: lambdaptr_tides_deriv
real(DP), dimension(:,:), allocatable :: xbeg
real(DP), dimension(:,:), allocatable :: xend
real(DP) :: dt
contains
generic :: init => tides_derivs_init
procedure :: evalt => tides_derivs_eval
procedure, nopass :: tides_derivs_init
end type
interface lambda_obj
module procedure tides_derivs_init
end interface
abstract interface
function tidederiv(x, t, dt, xbeg, xend) result(y)
! Template for a 0 argument function
import DP, swiftest_nbody_system
real(DP), dimension(:), intent(in) :: x
real(DP), intent(in) :: t
real(DP), intent(in) :: dt
real(DP), dimension(:,:), intent(in) :: xbeg
real(DP), dimension(:,:), intent(in) :: xend
real(DP), dimension(:), allocatable :: y
end function
end interface

contains
module subroutine tides_step_spin_system(self, param, t, dt)
!! author: Jennifer L.L. Pouplin and David A. Minton
!!
!! Integrates the spin equations for central and massive bodies of the system subjected to tides.
implicit none
! Arguments
class(swiftest_nbody_system), intent(inout) :: self !! Swiftest nbody system object
class(swiftest_parameters), intent(in) :: param !! Current run configuration parameters
real(DP), intent(in) :: t !! Simulation time
real(DP), intent(in) :: dt !! Current stepsize
! Internals
real(DP), dimension(:), allocatable :: rot0, rot1
real(DP) :: subt
real(DP), parameter :: tol=1e-6_DP !! Just a guess at the moment
real(DP) :: subdt

associate(pl => self%pl, npl => self%pl%nbody, cb => self%cb)
allocate(rot0(NDIM*(npl+1)))
rot0 = [pack(pl%rot(:,1:npl),.true.), pack(cb%rot(:),.true.)]
! Use this space call the ode_solver, passing tides_spin_derivs as the function:
subdt = dt / 20._DP
!rot1(:) = util_solve_rkf45(lambda_obj(tides_spin_derivs, subdt, pl%xbeg, pl%xend), rot0, dt, subdt tol)
! Recover with unpack
!pl%rot(:,1:npl) = unpack(rot1...
!cb%rot(:) = unpack(rot1...
end associate

return
end subroutine tides_step_spin_system

function tides_spin_derivs(rot_pl_cb, t, dt, xbeg, xend) result(drot) !! Need to add more arguments so we can pull in mass, radius, Ip, J2, etc...
!! author: Jennifer L.L. Pouplin and David A. Minton
!!
!! function used to calculate the derivatives that are fed to the ODE solver
implicit none
! Arguments
real(DP), dimension(:,:), intent(in) :: rot_pl_cb !! Array of rotations. The last element is the central body, and all others are massive bodies
real(DP), intent(in) :: t !! Current time, which is used to interpolate the massive body positions
real(DP), intent(in) :: dt !! Total step size
real(DP), dimension(:,:), intent(in) :: xbeg
real(DP), dimension(:,:), intent(in) :: xend
! Internals
real(DP), dimension(:,:), allocatable :: drot
real(DP), dimension(:), allocatable :: flatrot
real(DP), dimension(NDIM) :: N_Tcb, N_Rcb, N_Tpl, N_Rpl, xinterp
real(DP) :: C_cb, C_pl, r_dot_rot_cb, r_dot_rot_pl, rmag
integer(I4B) :: i, n


n = size(rot_pl_cb,2)
if (allocated(drot)) deallocate(drot)
allocate(drot, mold=rot_pl_cb)
drot(:,:) = 0.0_DP
do i = 1,n-1
xinterp(:) = xbeg(:,i) + t / dt * (xend(:,i) - xbeg(:,i))
! Calculate Ncb and Npl as a function of xinterp
!drot(:,i) = -Mcb / (Mcb + Mpl(i)) * (N_Tpl + N_Rpl)
!drot(:,n) = drot(:,n) - Mcb / (Mcb + Mpl(i) * (N_Tcb + N_Rcb)
!
end do

end function tides_spin_derivs

function tides_derivs_eval(self, x, t) result(y)
implicit none
! Arguments
class(tides_derivs_func), intent(inout) :: self
real(DP), dimension(:), intent(in) :: x
real(DP), intent(in) :: t
! Result
real(DP), dimension(:), allocatable :: y
if (associated(self%lambdaptr_tides_deriv)) then
y = self%lambdaptr_tides_deriv(x, t, self%dt, self%xbeg, self%xend)
else
error stop "Lambda function was not initialized"
end if
end function tides_derivs_eval

function tides_derivs_init(lambda, dt, xbeg, xend) result(f)
implicit none
! Arguments
procedure(tidederiv) :: lambda
real(DP), intent(in) :: dt
real(DP), dimension(:,:), intent(in) :: xbeg
real(DP), dimension(:,:), intent(in) :: xend
! Result
type(tides_derivs_func) :: f
f%lambdaptr_tides_deriv => lambda
f%dt = dt
allocate(f%xbeg, source = xbeg)
allocate(f%xend, source = xend)
return
end function tides_derivs_init
end submodule s_tides_step_spin
27 changes: 21 additions & 6 deletions src/util/util_solve.f90
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ function util_solve_rkf45(f, y0in, t1, dt0, tol) result(y1)
real(DP), dimension(RKS), parameter :: rkf5_coeff = (/ 16./135., 0., 6656./12825., 28561./56430., -9./50., 2./55. /)
real(DP), dimension(:, :), allocatable :: k !! Runge-Kutta coefficient vector
real(DP), dimension(:), allocatable :: ynorm !! Normalized y value used for adaptive step size control
real(DP), dimension(:), allocatable :: y0 !! Value of y at the beginning of each substep
real(DP), dimension(:), allocatable :: y0 !! Value of y at the beginning of each substep
integer(I4B) :: Nvar !! Number of variables in problem
integer(I4B) :: rkn !! Runge-Kutta loop index
real(DP) :: dt, trem !! Current step size and total time remaining
real(DP) :: t, x1, dt, trem !! Current time, step size and total time remaining
real(DP) :: s, yerr, yscale !! Step size reduction factor, error in dependent variable, and error scale factor
integer(I4B) :: i, n

Expand All @@ -45,13 +45,27 @@ function util_solve_rkf45(f, y0in, t1, dt0, tol) result(y1)
dt = dt0

trem = t1
t = 0._DP
do
yscale = norm2(y0(:))
do i = 1, MAXREDUX
do rkn = 1, RKS
y1(:) = y0(:) + matmul(k(:, 1:rkn - 1), rkf45_btab(2:rkn, rkn - 1))
k(:, rkn) = dt * f%eval(y1(:))
end do
select type(f)
class is (lambda_obj_tvar)
do rkn = 1, RKS
y1(:) = y0(:) + matmul(k(:, 1:rkn - 1), rkf45_btab(2:rkn, rkn - 1))
if (rkn == 1) then
x1 = t
else
x1 = t + rkf45_btab(1,rkn-1)
end if
k(:, rkn) = dt * f%evalt(y1(:), t)
end do
class is (lambda_obj)
do rkn = 1, RKS
y1(:) = y0(:) + matmul(k(:, 1:rkn - 1), rkf45_btab(2:rkn, rkn - 1))
k(:, rkn) = dt * f%eval(y1(:))
end do
end select
! Now determine if the step size needs adjusting
ynorm(:) = matmul(k(:,:), (rkf5_coeff(:) - rkf4_coeff(:))) / yscale
yerr = norm2(ynorm(:))
Expand All @@ -67,6 +81,7 @@ function util_solve_rkf45(f, y0in, t1, dt0, tol) result(y1)
! Compute new value then step ahead in time
y1(:) = y0(:) + matmul(k(:, :), rkf4_coeff(:))
trem = trem - dt
t = t + dt
if (trem <= 0._DP) exit
y0(:) = y1(:)
end do
Expand Down

0 comments on commit d0126da

Please sign in to comment.