Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Runge-Kutta time integration #86

Merged
merged 36 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4ec4101
Add RK2 loop in time integration module
trhille Aug 31, 2023
bf947b6
Pass rkTend to advection routine
trhille Aug 31, 2023
c703988
Finalize thickness and tracers at end of RK loop
trhille Aug 31, 2023
bf88eb8
Correct dimensions of rkTend
trhille Aug 31, 2023
220e2a4
Update halos for rkTend in each step of RK loop
trhille Aug 31, 2023
9ccdde6
Ensure damage >= damageNye after RK integration
trhille Aug 31, 2023
5d1e573
Generalize RK time integration
trhille Sep 3, 2023
278a5d7
Fix forward Euler time integration
trhille Sep 4, 2023
af21705
Rename files, modules, and routines to include Runge-Kutta
trhille Sep 4, 2023
63a169b
Add SSP-RK3 time integration
trhille Sep 4, 2023
b920b33
Update RK2 and RK4 substeps using 0th step solution
trhille Sep 6, 2023
dc33a67
Only use SSP RK2 and RK3 methods
trhille Sep 7, 2023
74c014f
Some cleanup
trhille Sep 7, 2023
e938e92
Add option for 4-stage SSPRK3
trhille Sep 20, 2023
f0c9a1f
Include SMB and BMB within RK loop
trhille Sep 21, 2023
79b4635
Fix SMB and BMB budget for forward euler
trhille Sep 22, 2023
413f304
Some more cleanup
trhille Oct 3, 2023
954ecce
Fix bug in groundedSfcMassBalApplied after Runge-Kutta loop
trhille Oct 4, 2023
606cbb0
Calculate groundedToFloatingThickness and grounding line flux after RK
trhille Oct 4, 2023
35fe8fa
Reset layerThickness when using config_restore_thickness_after_advection
trhille Oct 5, 2023
07fdc99
Update stresses and strain rates after calving
trhille Oct 6, 2023
f875198
Update thickness and tracer halos before velocity solve
trhille Oct 6, 2023
20fdec7
Update temperature and waterFrac in RK loop, but not enthalpy
trhille Oct 9, 2023
fbb6d6d
Simple clean-up after code review
trhille Oct 27, 2023
d7eac5c
Initialize RK weights to large negative values
trhille Oct 30, 2023
3bcd1d9
Restore calving front within RK loop
trhille Oct 30, 2023
13f0908
Remove support for config_rk_order = 1
trhille Oct 30, 2023
e7e1f30
Include calving in Runge-Kutta loop
trhille Oct 31, 2023
add0633
Calculate layerThickness after calving in RK loop
trhille Nov 2, 2023
7073b89
Revert "Calculate layerThickness after calving in RK loop"
trhille Nov 6, 2023
fb0315f
Revert "Include calving in Runge-Kutta loop"
trhille Nov 6, 2023
51802e1
Average fluxAcrossGroundingLineOnCells in time integration module
trhille Nov 6, 2023
ca28f5b
Add logic to control whether velocity is solved before and/or after c…
trhille Nov 8, 2023
4cda648
Make config_update_velocity_before_calving = .false. the default
trhille Nov 8, 2023
9ac9af2
Always update velocity after calving if it was not updated before cal…
trhille Nov 8, 2023
e2a2f0b
Move subglacial hydro and bed topography updates back to their former…
trhille Nov 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions components/mpas-albany-landice/src/Registry.xml
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@
description="If true, then distribute unablatedVolumeDynCell among dynamic neighbors when converting ablation velocity to ablation thickness. This should only be used as a clean-up measure, while limiting the timestep based on ablation velocity should be used as the primary method of getting accurate ablation thickness from ablation velocity. If you choose to set config_adaptive_timestep_calvingCFL_fraction much larger than 1.0 (which is not recommended), setting this option to true usually results in more accurate calving behavior. "
possible_values=".true. or .false."
/>
<nml_option name="config_update_velocity_before_calving" type="logical" default_value=".false." units="unitless"
description="If true, add an additional velocity solve between advection and calving. If false, use velocity field from beginning of time step to calculate calving rate. For certain calving laws, like damage threshold calving, it is not necessary to update the velocity before calving, while for von Mises stress and eigencalving, it is more accurate to have an updated velocity state before solving for calvingThickness."
possible_values=".true. or .false."
/>
</nml_record>

<nml_record name="thermal_solver" in_defaults="true">
Expand Down Expand Up @@ -485,8 +489,16 @@
possible_values="Any time interval of the format 'YYYY-MM-DD_HH:MM:SS', but limited by CFL condition."
/>
<nml_option name="config_time_integration" type="character" default_value="forward_euler" units="unitless"
description="Time integration method (currently, only forward Euler is supported)."
possible_values="'forward_euler'"
description="Time integration method."
possible_values="'forward_euler' or 'runge_kutta'"
/>
<nml_option name="config_rk_order" type="integer" default_value="2" units="unitless"
description="Order of Runge-Kutta time integration to use. A value of 1 would be equivalent to forward euler, but will cause an error to avoid unnecessary redundancy. Values of 2 and 3 indicate strong-stability preserving RK2 and RK3. There is currently no support for classical RK2 or RK4 methods."
possible_values="2 or 3"
/>
<nml_option name="config_rk3_stages" type="integer" default_value="3" units="stages"
description="Number of stages for strong stability preserving RK3 time integration. If set to 3, this involves 3 velocity solves and a maximum CFL fraction of 1. If set to 4, this involves 4 velocity solves, but the maximum CFL fraction is 2."
possible_values="3 or 4"
/>
<nml_option name="config_adaptive_timestep" type="logical" default_value=".false." units="unitless"
description="Determines if the time step should be adjusted based on the CFL condition or should be steady in time. If true, the config_dt_* options are ignored."
Expand Down
2 changes: 1 addition & 1 deletion components/mpas-albany-landice/src/landice.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ list(APPEND RAW_SOURCES
core_landice/mode_forward/mpas_li_core.F
core_landice/mode_forward/mpas_li_core_interface.F
core_landice/mode_forward/mpas_li_time_integration.F
core_landice/mode_forward/mpas_li_time_integration_fe.F
core_landice/mode_forward/mpas_li_time_integration_fe_rk.F
core_landice/mode_forward/mpas_li_diagnostic_vars.F
core_landice/mode_forward/mpas_li_advection.F
core_landice/mode_forward/mpas_li_calving.F
Expand Down
6 changes: 3 additions & 3 deletions components/mpas-albany-landice/src/mode_forward/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
OBJS = mpas_li_core.o \
mpas_li_core_interface.o \
mpas_li_time_integration.o \
mpas_li_time_integration_fe.o \
mpas_li_time_integration_fe_rk.o \
mpas_li_diagnostic_vars.o \
mpas_li_advection.o \
mpas_li_advection_fct_shared.o \
Expand Down Expand Up @@ -35,9 +35,9 @@ mpas_li_core.o: mpas_li_time_integration.o \
mpas_li_statistics.o \
mpas_li_calving.o

mpas_li_time_integration.o: mpas_li_time_integration_fe.o
mpas_li_time_integration.o: mpas_li_time_integration_fe_rk.o

mpas_li_time_integration_fe.o: mpas_li_advection.o \
mpas_li_time_integration_fe_rk.o: mpas_li_advection.o \
mpas_li_calving.o \
mpas_li_thermal.o \
mpas_li_iceshelf_melt.o \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ module li_advection
!--------------------------------------------------------------------
public :: li_advection_thickness_tracers, &
li_layer_normal_velocity, &
li_update_geometry
li_update_geometry, &
li_grounded_to_floating

!--------------------------------------------------------------------
!
Expand Down Expand Up @@ -629,10 +630,6 @@ subroutine li_advection_thickness_tracers(&
call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp)
err = ior(err, err_tmp)

! Calculate volume converted from grounded to floating
! This needs to be determined after SMB/BMB are applied because those can change floating/grounded state
call grounded_to_floating(cellMaskTemporaryField % array, cellMask, thickness, groundedToFloatingThickness, nCells)

! Calculate flux across grounding line
! Do this after new thickness & mask have been calculated, including SMB/BMB
fluxAcrossGroundingLine(:) = 0.0_RKIND
Expand Down Expand Up @@ -2107,7 +2104,7 @@ subroutine vertical_remap(thickness, cellMask, meshPool, layerThickness, tracers

end subroutine vertical_remap

subroutine grounded_to_floating(cellMaskOrig, cellMaskNew, thicknessNew, groundedToFloatingThickness, nCells)
subroutine li_grounded_to_floating(cellMaskOrig, cellMaskNew, thicknessNew, groundedToFloatingThickness, nCells)
!-----------------------------------------------------------------
! input variables
!-----------------------------------------------------------------
Expand Down Expand Up @@ -2151,7 +2148,7 @@ subroutine grounded_to_floating(cellMaskOrig, cellMaskNew, thicknessNew, grounde
endif
enddo

end subroutine grounded_to_floating
end subroutine li_grounded_to_floating

!***********************************************************************

Expand Down
44 changes: 38 additions & 6 deletions components/mpas-albany-landice/src/mode_forward/mpas_li_calving.F
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ module li_calving
!> (3) Calve ice based on an ice thickness threshold
!-----------------------------------------------------------------------

subroutine li_calve_ice(domain, err)
subroutine li_calve_ice(domain, err, solveVeloAfterCalving)

use li_advection

Expand All @@ -92,7 +92,7 @@ subroutine li_calve_ice(domain, err)
! output variables
!-----------------------------------------------------------------
integer, intent(out) :: err !< Output: error flag

logical, intent(out), optional :: solveVeloAfterCalving
!-----------------------------------------------------------------
! local variables
!-----------------------------------------------------------------
Expand All @@ -111,13 +111,14 @@ subroutine li_calve_ice(domain, err)
logical, pointer :: config_apply_calving_mask
real(kind=RKIND), pointer :: config_calving_timescale

integer, pointer :: nCells
integer, pointer :: nCells, nCellsSolve
integer, pointer :: config_number_of_blocks

real (kind=RKIND), pointer :: deltat !< time step (s)

integer, dimension(:), pointer :: &
indexToCellID ! list of global cell IDs
indexToCellID, & ! list of global cell IDs
cellMask

real (kind=RKIND) :: &
calvingFraction ! fraction of ice that calves in each column; depends on calving_timescale
Expand All @@ -136,14 +137,22 @@ subroutine li_calve_ice(domain, err)

real (kind=RKIND), dimension(:), pointer :: calvingVelocity

real (kind=RKIND), dimension(:), pointer :: areaCell

type (field1dReal), pointer :: originalThicknessField

real (kind=RKIND), dimension(:), pointer :: originalThickness

type (field1dInteger), pointer :: cellMaskTemporaryField

integer :: iCell

real (kind=RKIND), parameter :: smallNumber = 1.0e-6_RKIND

integer :: err_tmp

real (kind=RKIND), dimension(1) :: calvingSumLocal, calvingSumGlobal

err = 0
err_tmp = 0

Expand All @@ -155,6 +164,15 @@ subroutine li_calve_ice(domain, err)
call mpas_pool_get_config(liConfigs, 'config_data_calving', config_data_calving)
call mpas_pool_get_config(liConfigs, 'config_number_of_blocks', config_number_of_blocks)

if (present(solveVeloAfterCalving)) then
call mpas_pool_get_subpool(domain % blocklist % structs, 'geometry', geometryPool)
call mpas_pool_get_field(geometryPool, 'cellMaskTemporary', cellMaskTemporaryField)
call mpas_allocate_scratch_field(cellMaskTemporaryField, .true.)
call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
! Store cellMask prior to calving
cellMaskTemporaryField % array(:) = cellMask(:)
endif

! Zero calvingThickness here instead of or in addition to in individual subroutines.
! This is necessary when using damage threshold calving with other calving
! routines. Some individual routines still set calvingThickness to zero, but
Expand Down Expand Up @@ -206,7 +224,7 @@ subroutine li_calve_ice(domain, err)
! However, the eigencalving method requires multiple applications of the calvingThickness
! to the thickness. So the simplest method to apply data calving is to store the old
! thickness and then set it back when we are done.
if (config_data_calving) then
if ( config_data_calving .or. present(solveVeloAfterCalving) ) then
call mpas_pool_get_subpool(domain % blocklist % structs, 'scratch', scratchPool)
call mpas_pool_get_field(scratchPool, 'workCell2', originalThicknessField)
call mpas_allocate_scratch_field(originalThicknessField, single_block_in = .false.)
Expand Down Expand Up @@ -337,8 +355,22 @@ subroutine li_calve_ice(domain, err)

block => block % next
end do
if (present(solveVeloAfterCalving)) then
call mpas_pool_get_array(meshPool, 'areaCell', areaCell)
call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
calvingSumLocal(1) = sum(calvingThickness(1:nCellsSolve) * areaCell(1:nCellsSolve) * &
real(li_mask_is_dynamic_ice_int(cellMaskTemporaryField % array(1:nCellsSolve)), RKIND))
call mpas_dmpar_sum_real_array(domain % dminfo, 1, calvingSumLocal(1), calvingSumGlobal(1))
if (calvingSumGlobal(1) > smallNumber) then
solveVeloAfterCalving = .true.
else
solveVeloAfterCalving = .false.
endif
call mpas_deallocate_scratch_field(cellMaskTemporaryField, .true.)
endif

if (config_data_calving) then
if ( config_data_calving .or. present(solveVeloAfterCalving) ) then
call mpas_deallocate_scratch_field(originalThicknessField, single_block_in=.false.)
endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module li_time_integration
use mpas_timekeeping
use mpas_log

use li_time_integration_fe
use li_time_integration_fe_rk
use li_setup
use li_constants

Expand Down Expand Up @@ -166,10 +166,9 @@ subroutine li_timestep(domain, err)
!call mpas_log_write('Using ' // trim(config_time_integration) // ' time integration.')
select case (config_time_integration)
case ('forward_euler')
call li_time_integrator_forwardeuler(domain, err_tmp)
case ('rk4')
call mpas_log_write(trim(config_time_integration) // ' is not currently supported.', MPAS_LOG_ERR)
err_tmp = 1
call li_time_integrator_forwardeuler_rungekutta(domain, err_tmp)
case ('runge_kutta')
call li_time_integrator_forwardeuler_rungekutta(domain, err_tmp)
case default
call mpas_log_write(trim(config_time_integration) // ' is not a valid land ice time integration option.', MPAS_LOG_ERR)
err_tmp = 1
Expand Down
Loading