From 7565478d2712be5e39c8c9ac5d2a2f2b1ca832ba Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Wed, 29 Sep 2021 12:09:07 -0500 Subject: [PATCH 01/13] first draft API based on Luyu's code --- .../external/drifters/MOM_particles.F90 | 43 ++++++++++++ .../external/drifters/MOM_particles_types.F90 | 65 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 config_src/external/drifters/MOM_particles.F90 create mode 100644 config_src/external/drifters/MOM_particles_types.F90 diff --git a/config_src/external/drifters/MOM_particles.F90 b/config_src/external/drifters/MOM_particles.F90 new file mode 100644 index 0000000000..b70fe4d11f --- /dev/null +++ b/config_src/external/drifters/MOM_particles.F90 @@ -0,0 +1,43 @@ +!> A set of dummy interfaces for compiling the MOM6 drifters code +module MOM_particles_mod + +use MOM_time_manager, only : time_type, get_date, operator(-) +use MOM_variables, only : thermo_var_ptrs + + +use particles_types_mod, only: particles, particles_gridded + +public particles_run + +contains + +subroutine particles_init(parts, Grid, Time, dt, u, v) + type(particles), pointer, intent(out) :: parts + type(ocean_grid_type), target, intent(in) :: Grid !< Grid type from parent model + type(time_type), intent(in) :: Time !< Time type from parent model + real, intent(in) :: dt !< particle timestep in seconds + real, dimension(:,:,:),intent(in) :: u, v !< Horizontal velocity fields + +end subroutine particles_init + + +subroutine particles_run(parts, time, uo, vo, ho, tv, stagger) + ! Arguments + type(particles), pointer :: parts !< Container for all types and memory + type(time_type), intent(in) :: time !< Model time + real, dimension(:,:,:),intent(in) :: uo !< Ocean zonal velocity (m/s) + real, dimension(:,:,:),intent(in) :: vo !< Ocean meridional velocity (m/s) + real, dimension(:,:,:),intent(in) :: ho !< Ocean layer thickness [H ~> m or kg m-2] + type(thermo_var_ptrs), intent(in) :: tv !< structure containing pointers to available thermodynamic fields + integer, optional, intent(in) :: stagger + +end subroutine particles_run + +subroutine particles_save_restart(parts,temp,salt) +! Arguments +type(particles), pointer :: parts +real,dimension(:,:,:),optional,intent(in) :: temp, salt + +end subroutine particles_save_restart + +end module MOM_particles_mod diff --git a/config_src/external/drifters/MOM_particles_types.F90 b/config_src/external/drifters/MOM_particles_types.F90 new file mode 100644 index 0000000000..aad618145f --- /dev/null +++ b/config_src/external/drifters/MOM_particles_types.F90 @@ -0,0 +1,65 @@ +!> Dummy data structures and methods for drifters package +module particles_types_mod + + +!>xyt is a data structure containing particle position and velocity fields. +type :: xyt + real :: lon, lat, day !< Current position (degrees) and day + real :: lat_old, lon_old !< Previous position (degrees) + real :: uvel, vvel !< Current velocity components (m/s) + real :: uvel_old, vvel_old !< Previous velocity components (m/s) + integer :: year, particle_num !< Current year and particle number + integer(kind=8) :: id = -1 !< Particle Identifier + type(xyt), pointer :: next=>null() !< Pointer to the next position in the list +end type xyt + + +!>A buffer structure for message passing +type :: buffer + integer :: size=0 + real, dimension(:,:), pointer :: data +end type buffer + +!> A wrapper for the particle linked list (since an array of pointers is not allowed) +type :: linked_list + type(particle), pointer :: first=>null() !< Pointer to the beginning of a linked list of parts +end type linked_list + + +type :: particles !; private + type(particles_gridded) :: grd !< Container with all gridded data + type(linked_list), dimension(:,:), allocatable :: list !< Linked list of particles + type(xyt), pointer :: trajectories=>null() !< A linked list for detached segments of trajectories + real :: dt !< Time-step between particle calls + integer :: current_year !< Current year (years) + real :: current_yearday !< Current year-day, 1.00-365.99, (days) + integer :: traj_sample_hrs !< Period between sampling for trajectories (hours) + integer :: traj_write_hrs !< Period between writing of trajectories (hours) + integer :: verbose_hrs !< Period between terminal status reports (hours) + !>@{ + !! Handles for clocks + integer :: clock, clock_mom, clock_the, clock_int, clock_cal, clock_com, clock_ini, clock_ior, clock_iow, clock_dia + integer :: clock_trw, clock_trp + !>@} + logical :: restarted=.false. !< Indicate whether we read state from a restart or not + logical :: Runge_not_Verlet=.True. !< True=Runge-Kutta, False=Verlet. + logical :: ignore_missing_restart_parts=.False. !< True allows the model to ignore particles missing in the restart. + logical :: halo_debugging=.False. !< Use for debugging halos (remove when its working) + logical :: save_short_traj=.false. !< True saves only lon,lat,time,id in particle_trajectory.nc + logical :: ignore_traj=.False. !< If true, then model does not write trajectory data at all + logical :: use_new_predictive_corrective =.False. !< Flag to use Bob's predictive corrective particle scheme- Added by Alon + integer(kind=8) :: debug_particle_with_id = -1 !< If positive, monitors a part with this id + type(buffer), pointer :: obuffer_n=>null() !< Buffer for outgoing parts to the north + type(buffer), pointer :: ibuffer_n=>null() !< Buffer for incoming parts from the north + type(buffer), pointer :: obuffer_s=>null() !< Buffer for outgoing parts to the south + type(buffer), pointer :: ibuffer_s=>null() !< Buffer for incoming parts from the south + type(buffer), pointer :: obuffer_e=>null() !< Buffer for outgoing parts to the east + type(buffer), pointer :: ibuffer_e=>null() !< Buffer for incoming parts from the east + type(buffer), pointer :: obuffer_w=>null() !< Buffer for outgoing parts to the west + type(buffer), pointer :: ibuffer_w=>null() !< Buffer for incoming parts from the west + type(buffer), pointer :: obuffer_io=>null() !< Buffer for outgoing parts during i/o + type(buffer), pointer :: ibuffer_io=>null() !< Buffer for incoming parts during i/o +end type particles + + +end module particles_types_mod From 04e6138fed9ca8945724260cac1e22335339b193 Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Wed, 29 Sep 2021 12:49:57 -0500 Subject: [PATCH 02/13] fixed various errors --- .../external/drifters/MOM_particles.F90 | 1 + .../external/drifters/MOM_particles_types.F90 | 75 +++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/config_src/external/drifters/MOM_particles.F90 b/config_src/external/drifters/MOM_particles.F90 index b70fe4d11f..8208441f1a 100644 --- a/config_src/external/drifters/MOM_particles.F90 +++ b/config_src/external/drifters/MOM_particles.F90 @@ -1,6 +1,7 @@ !> A set of dummy interfaces for compiling the MOM6 drifters code module MOM_particles_mod +use MOM_grid, only : ocean_grid_type use MOM_time_manager, only : time_type, get_date, operator(-) use MOM_variables, only : thermo_var_ptrs diff --git a/config_src/external/drifters/MOM_particles_types.F90 b/config_src/external/drifters/MOM_particles_types.F90 index aad618145f..36ecd1eb01 100644 --- a/config_src/external/drifters/MOM_particles_types.F90 +++ b/config_src/external/drifters/MOM_particles_types.F90 @@ -1,6 +1,62 @@ !> Dummy data structures and methods for drifters package module particles_types_mod +use MOM_grid, only : ocean_grid_type +use mpp_domains_mod, only: domain2D + + +!> Container for gridded fields +type :: particles_gridded + type(domain2D), pointer :: domain !< MPP parallel domain + integer :: halo !< Nominal halo width + integer :: isc !< Start i-index of computational domain + integer :: iec !< End i-index of computational domain + integer :: jsc !< Start j-index of computational domain + integer :: jec !< End j-index of computational domain + integer :: isd !< Start i-index of data domain + integer :: ied !< End i-index of data domain + integer :: jsd !< Start j-index of data domain + integer :: jed !< End j-index of data domain + integer :: isg !< Start i-index of global domain + integer :: ieg !< End i-index of global domain + integer :: jsg !< Start j-index of global domain + integer :: jeg !< End j-index of global domain + integer :: is_offset=0 !< add to i to recover global i-index + integer :: js_offset=0 !< add to j to recover global j-index + integer :: my_pe !< MPI PE index + integer :: pe_N !< MPI PE index of PE to the north + integer :: pe_S !< MPI PE index of PE to the south + integer :: pe_E !< MPI PE index of PE to the east + integer :: pe_W !< MPI PE index of PE to the west + logical :: grid_is_latlon !< Flag to say whether the coordinate is in lat-lon degrees, or meters + logical :: grid_is_regular !< Flag to say whether point in cell can be found assuming regular Cartesian grid + real :: Lx !< Length of the domain in x direction + real, dimension(:,:), pointer :: lon=>null() !< Longitude of cell corners (degree E) + real, dimension(:,:), pointer :: lat=>null() !< Latitude of cell corners (degree N) + real, dimension(:,:), pointer :: lonc=>null() !< Longitude of cell centers (degree E) + real, dimension(:,:), pointer :: latc=>null() !< Latitude of cell centers (degree N) + real, dimension(:,:), pointer :: dx=>null() !< Length of cell edge (m) + real, dimension(:,:), pointer :: dy=>null() !< Length of cell edge (m) + real, dimension(:,:), pointer :: area=>null() !< Area of cell (m^2) + real, dimension(:,:), pointer :: msk=>null() !< Ocean-land mask (1=ocean) + real, dimension(:,:), pointer :: cos=>null() !< Cosine from rotation matrix to lat-lon coords + real, dimension(:,:), pointer :: sin=>null() !< Sine from rotation matrix to lat-lon coords + real, dimension(:,:), pointer :: ocean_depth=>NULL() !< Depth of ocean (m) + real, dimension(:,:), pointer :: uo=>null() !< Ocean zonal flow (m/s) + real, dimension(:,:), pointer :: vo=>null() !< Ocean meridional flow (m/s) + real, dimension(:,:), pointer :: tmp=>null() !< Temporary work space + real, dimension(:,:), pointer :: tmpc=>null() !< Temporary work space + real, dimension(:,:), pointer :: parity_x=>null() !< X component of vector point from i,j to i+1,j+1 (for detecting tri-polar fold) + real, dimension(:,:), pointer :: parity_y=>null() !< Y component of vector point from i,j to i+1,j+1 (for detecting tri-polar fold) + integer, dimension(:,:), pointer :: particle_counter_grd=>null() !< Counts particles created for naming purposes + !>@{ + !! Diagnostic handle + integer :: id_uo=-1, id_vo=-1, id_unused=-1 + integer :: id_count=-1, id_chksum=-1 + !>@} + +end type particles_gridded + !>xyt is a data structure containing particle position and velocity fields. type :: xyt @@ -13,6 +69,25 @@ module particles_types_mod type(xyt), pointer :: next=>null() !< Pointer to the next position in the list end type xyt +!>particle types are data structures describing a tracked particle +type :: particle + type(particle), pointer :: prev=>null(), next=>null() + ! State variables (specific to the particle, needed for restarts) + real :: lon, lat, depth, uvel, vvel !< position (degrees) and zonal and meridional velocities (m/s) + real :: lon_old, lat_old, uvel_old, vvel_old !< previous position (degrees) and zonal + !< and meridional velocities (m/s) + real :: axn, ayn, bxn, byn !< explicit and implicit accelerations (currently disabled) + real :: start_lon, start_lat, start_day !< origination position (degrees) and day + integer :: start_year !< origination year + real :: halo_part !< equal to zero for particles on the computational domain, and 1 for particles on the halo + integer(kind=8) :: id,drifter_num !< particle identifier + integer :: ine, jne !< nearest index in NE direction (for convenience) + real :: xi, yj !< non-dimensional coords within current cell (0..1) + real :: uo, vo !< zonal and meridional ocean velocities experienced + !< by the particle (m/s) + type(xyt), pointer :: trajectory=>null() +end type particle + !>A buffer structure for message passing type :: buffer From be07bb66a5b9f044b2777033dd690ccd7ac1938a Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Fri, 1 Oct 2021 17:21:49 -0500 Subject: [PATCH 03/13] Code for particles in MOM.F90 --- src/core/MOM.F90 | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 4865e543c9..d7a27fcf37 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -47,6 +47,7 @@ module MOM use MOM_time_manager, only : time_type, real_to_time, time_type_to_real, operator(+) use MOM_time_manager, only : operator(-), operator(>), operator(*), operator(/) use MOM_time_manager, only : operator(>=), operator(==), increment_date +use MOM_time_manager, only : set_time use MOM_unit_tests, only : unit_tests ! MOM core modules @@ -150,6 +151,7 @@ module MOM use MOM_offline_main, only : offline_advection_layer, offline_transport_end use MOM_ALE, only : ale_offline_tracer_final, ALE_main_offline use MOM_ice_shelf, only : ice_shelf_CS, ice_shelf_query, initialize_ice_shelf +use MOM_particles_mod, only : particles, particles_init, particles_run, particles_save_restart implicit none ; private @@ -324,6 +326,8 @@ module MOM logical :: answers_2018 !< If true, use expressions for the surface properties that recover !! the answers from the end of 2018. Otherwise, use more appropriate !! expressions that differ at roundoff for non-Boussinsq cases. + logical :: use_particles !< Turns on the particles package + character(len=10) :: particle_type !< Particle types include: surface(default), profiling and sail drone. type(MOM_diag_IDs) :: IDs !< Handles used for diagnostics. type(transport_diag_IDs) :: transport_IDs !< Handles used for transport diagnostics. @@ -391,6 +395,7 @@ module MOM type(ODA_CS), pointer :: odaCS => NULL() !< a pointer to the control structure for handling !! ensemble model state vectors and data assimilation !! increments and priors + type(particles), pointer :: particles => NULL() ! Date: Tue, 5 Oct 2021 12:09:32 -0500 Subject: [PATCH 04/13] moved particles_run into dynamics step --- src/core/MOM.F90 | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index d7a27fcf37..b9710ff454 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -1014,6 +1014,7 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, & integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB + type(time_type) :: part_time G => CS%G ; GV => CS%GV ; US => CS%US ; IDs => CS%IDs is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke @@ -1097,6 +1098,14 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, & endif ! -------------------------------------------------- end SPLIT + if (CS%do_dynamics) then!run particles whether or not stepping is split + if (CS%use_particles) then + part_time = CS%Time + set_time(int(dt)) + call particles_run(CS%particles, part_time, CS%u, CS%v, CS%h, CS%tv) ! Run the particles model + endif + endif + + if (CS%thickness_diffuse .and. .not.CS%thickness_diffuse_first) then call cpu_clock_begin(id_clock_thick_diff) @@ -1270,7 +1279,6 @@ subroutine step_MOM_thermo(CS, G, GV, US, u, v, h, tv, fluxes, dtdia, & ! in the dynamic core. integer :: halo_sz ! The size of a halo where data must be valid. integer :: i, j, k, is, ie, js, je, nz - type(time_type) :: part_time is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke showCallTree = callTree_showQuery() @@ -1434,10 +1442,6 @@ subroutine step_MOM_thermo(CS, G, GV, US, u, v, h, tv, fluxes, dtdia, & call disable_averaging(CS%diag) if (showCallTree) call callTree_leave("step_MOM_thermo(), MOM.F90") - if (CS%use_particles) then - part_time = CS%Time + set_time(int(floor(0.5 + 0.5*dtdia))) - call particles_run(CS%particles, part_time, CS%u, CS%v, CS%h, CS%tv) ! Run the particles model - endif end subroutine step_MOM_thermo From 90dd8570a97714a166faa20eaeb37aa3b2331b85 Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Tue, 5 Oct 2021 14:28:25 -0500 Subject: [PATCH 05/13] added particles_end --- config_src/external/drifters/MOM_particles.F90 | 9 ++++++++- src/core/MOM.F90 | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/config_src/external/drifters/MOM_particles.F90 b/config_src/external/drifters/MOM_particles.F90 index 8208441f1a..cf9078df57 100644 --- a/config_src/external/drifters/MOM_particles.F90 +++ b/config_src/external/drifters/MOM_particles.F90 @@ -8,7 +8,7 @@ module MOM_particles_mod use particles_types_mod, only: particles, particles_gridded -public particles_run +public particles_run, particles_init, particles_save_restart, particles_end contains @@ -41,4 +41,11 @@ subroutine particles_save_restart(parts,temp,salt) end subroutine particles_save_restart +subroutine particles_end(parts,temp,salt) +! Arguments +type(particles), pointer :: parts +real,dimension(:,:,:),optional,intent(in) :: temp, salt + +end subroutine particles_end + end module MOM_particles_mod diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index b9710ff454..954ea12d07 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -151,7 +151,7 @@ module MOM use MOM_offline_main, only : offline_advection_layer, offline_transport_end use MOM_ALE, only : ale_offline_tracer_final, ALE_main_offline use MOM_ice_shelf, only : ice_shelf_CS, ice_shelf_query, initialize_ice_shelf -use MOM_particles_mod, only : particles, particles_init, particles_run, particles_save_restart +use MOM_particles_mod, only : particles, particles_init, particles_run, particles_save_restart, particles_end implicit none ; private @@ -3583,6 +3583,11 @@ subroutine MOM_end(CS) call end_dyn_unsplit(CS%dyn_unsplit_CSp) endif + if (CS%use_particles) then + call particles_end(CS%particles) + deallocate(CS%particles) + endif + call thickness_diffuse_end(CS%thickness_diffuse_CSp, CS%CDp) deallocate(CS%thickness_diffuse_CSp) From 356b350b75de064b8c3e2b156bb5c1c5b68500f9 Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Tue, 5 Oct 2021 17:22:33 -0500 Subject: [PATCH 06/13] Fixed particle time --- src/core/MOM.F90 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index 954ea12d07..c65794d08a 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -1014,7 +1014,6 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, & integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz integer :: isd, ied, jsd, jed, IsdB, IedB, JsdB, JedB - type(time_type) :: part_time G => CS%G ; GV => CS%GV ; US => CS%US ; IDs => CS%IDs is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = GV%ke @@ -1100,8 +1099,7 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, & if (CS%do_dynamics) then!run particles whether or not stepping is split if (CS%use_particles) then - part_time = CS%Time + set_time(int(dt)) - call particles_run(CS%particles, part_time, CS%u, CS%v, CS%h, CS%tv) ! Run the particles model + call particles_run(CS%particles, Time_local, CS%u, CS%v, CS%h, CS%tv) ! Run the particles model endif endif From 1893c637a0b4a83a5f8becae6553240f752b48af Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Tue, 5 Oct 2021 18:08:48 -0500 Subject: [PATCH 07/13] Fixed some documentation --- .../external/drifters/MOM_particles.F90 | 9 ++- .../external/drifters/MOM_particles_types.F90 | 57 ++++++++++++------- src/core/MOM.F90 | 2 +- 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/config_src/external/drifters/MOM_particles.F90 b/config_src/external/drifters/MOM_particles.F90 index cf9078df57..1a7f603710 100644 --- a/config_src/external/drifters/MOM_particles.F90 +++ b/config_src/external/drifters/MOM_particles.F90 @@ -12,8 +12,10 @@ module MOM_particles_mod contains +!> Initializes particles container "parts" subroutine particles_init(parts, Grid, Time, dt, u, v) - type(particles), pointer, intent(out) :: parts + ! Arguments + type(particles), pointer, intent(out) :: parts !< Container for all types and memory type(ocean_grid_type), target, intent(in) :: Grid !< Grid type from parent model type(time_type), intent(in) :: Time !< Time type from parent model real, intent(in) :: dt !< particle timestep in seconds @@ -21,7 +23,7 @@ subroutine particles_init(parts, Grid, Time, dt, u, v) end subroutine particles_init - +!> The main driver the steps updates particles subroutine particles_run(parts, time, uo, vo, ho, tv, stagger) ! Arguments type(particles), pointer :: parts !< Container for all types and memory @@ -34,6 +36,8 @@ subroutine particles_run(parts, time, uo, vo, ho, tv, stagger) end subroutine particles_run + +!>Save particle locations (and sometimes other vars) to restart file subroutine particles_save_restart(parts,temp,salt) ! Arguments type(particles), pointer :: parts @@ -41,6 +45,7 @@ subroutine particles_save_restart(parts,temp,salt) end subroutine particles_save_restart +!> Deallocate all memory and disassociated pointer subroutine particles_end(parts,temp,salt) ! Arguments type(particles), pointer :: parts diff --git a/config_src/external/drifters/MOM_particles_types.F90 b/config_src/external/drifters/MOM_particles_types.F90 index 36ecd1eb01..bc20bba32d 100644 --- a/config_src/external/drifters/MOM_particles_types.F90 +++ b/config_src/external/drifters/MOM_particles_types.F90 @@ -60,39 +60,57 @@ module particles_types_mod !>xyt is a data structure containing particle position and velocity fields. type :: xyt - real :: lon, lat, day !< Current position (degrees) and day - real :: lat_old, lon_old !< Previous position (degrees) - real :: uvel, vvel !< Current velocity components (m/s) - real :: uvel_old, vvel_old !< Previous velocity components (m/s) - integer :: year, particle_num !< Current year and particle number + real :: lon !< Longitude of particle (degree N or unit of grid coordinate) + real :: lat !< Latitude of particle (degree N or unit of grid coordinate) + real :: day !< Day of this record (days) + real :: lat_old !< Previous latitude + real :: lon_old !< Previous longitude + real :: uvel !< Zonal velocity of particle (m/s) + real :: vvel !< Meridional velocity of particle (m/s) + real :: uvel_old !< Previous zonal velocity component (m/s) + real :: vvel_old !< Previous meridional velocity component (m/s) + integer :: year !< Year of this record + integer :: particle_num !< Current particle number integer(kind=8) :: id = -1 !< Particle Identifier type(xyt), pointer :: next=>null() !< Pointer to the next position in the list end type xyt !>particle types are data structures describing a tracked particle type :: particle - type(particle), pointer :: prev=>null(), next=>null() - ! State variables (specific to the particle, needed for restarts) - real :: lon, lat, depth, uvel, vvel !< position (degrees) and zonal and meridional velocities (m/s) - real :: lon_old, lat_old, uvel_old, vvel_old !< previous position (degrees) and zonal - !< and meridional velocities (m/s) - real :: axn, ayn, bxn, byn !< explicit and implicit accelerations (currently disabled) - real :: start_lon, start_lat, start_day !< origination position (degrees) and day + type(particle), pointer :: prev=>null() !< Previous link in list + type(particle), pointer :: next=>null() +! State variables (specific to the particles, needed for restarts) + real :: lon !< Longitude of particle (degree N or unit of grid coordinate) + real :: lat !< Latitude of particle (degree E or unit of grid coordinate) + real :: depth !< Depth of particle + real :: uvel !< Zonal velocity of particle (m/s) + real :: vvel !< Meridional velocity of particle (m/s) + real :: lon_old !< previous lon (degrees) + real :: lat_old !< previous lat (degrees) + real :: uvel_old !< previous uvel + real :: vvel_old !< previous vvel + real :: start_lon !< starting longitude where particle was created + real :: start_lat !< starting latitude where particle was created + real :: start_day !< origination position (degrees) and day integer :: start_year !< origination year real :: halo_part !< equal to zero for particles on the computational domain, and 1 for particles on the halo - integer(kind=8) :: id,drifter_num !< particle identifier - integer :: ine, jne !< nearest index in NE direction (for convenience) - real :: xi, yj !< non-dimensional coords within current cell (0..1) - real :: uo, vo !< zonal and meridional ocean velocities experienced + integer(kind=8) :: id !< particle identifier + integer(kind=8) :: drifter_num !< particle identifier + integer :: ine !< nearest i-index in NE direction (for convenience) + integer :: jne !< nearest j-index in NE direction (for convenience) + real :: xi !< non-dimensional x-coordinate within current cell (0..1) + real :: yj !< non-dimensional y-coordinate within current cell (0..1) + real :: uo !< zonal ocean velocity + real :: vo !< meridional ocean velocity !< by the particle (m/s) - type(xyt), pointer :: trajectory=>null() + type(xyt), pointer :: trajectory=>null() !< Trajectory for this particle end type particle !>A buffer structure for message passing type :: buffer - integer :: size=0 - real, dimension(:,:), pointer :: data + integer :: size=0 !< Size of buffer + real, dimension(:,:), pointer :: data !< Buffer memory end type buffer !> A wrapper for the particle linked list (since an array of pointers is not allowed) @@ -101,6 +119,7 @@ module particles_types_mod end type linked_list +!> A grand data structure for the particles in the local MOM domain type :: particles !; private type(particles_gridded) :: grd !< Container with all gridded data type(linked_list), dimension(:,:), allocatable :: list !< Linked list of particles diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index c65794d08a..e9c050ad4a 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -1098,7 +1098,7 @@ subroutine step_MOM_dynamics(forces, p_surf_begin, p_surf_end, dt, dt_thermo, & endif ! -------------------------------------------------- end SPLIT if (CS%do_dynamics) then!run particles whether or not stepping is split - if (CS%use_particles) then + if (CS%use_particles) then call particles_run(CS%particles, Time_local, CS%u, CS%v, CS%h, CS%tv) ! Run the particles model endif endif From 010f98ea08745330904115b8197186a677556e4e Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Wed, 6 Oct 2021 10:07:10 -0500 Subject: [PATCH 08/13] Further documentation edits --- .../external/drifters/MOM_particles_types.F90 | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/config_src/external/drifters/MOM_particles_types.F90 b/config_src/external/drifters/MOM_particles_types.F90 index bc20bba32d..80335f7656 100644 --- a/config_src/external/drifters/MOM_particles_types.F90 +++ b/config_src/external/drifters/MOM_particles_types.F90 @@ -46,8 +46,9 @@ module particles_types_mod real, dimension(:,:), pointer :: vo=>null() !< Ocean meridional flow (m/s) real, dimension(:,:), pointer :: tmp=>null() !< Temporary work space real, dimension(:,:), pointer :: tmpc=>null() !< Temporary work space - real, dimension(:,:), pointer :: parity_x=>null() !< X component of vector point from i,j to i+1,j+1 (for detecting tri-polar fold) - real, dimension(:,:), pointer :: parity_y=>null() !< Y component of vector point from i,j to i+1,j+1 (for detecting tri-polar fold) + real, dimension(:,:), pointer :: parity_x=>null() !< X component of vector point from i,j to i+1,j+1 + real, dimension(:,:), pointer :: parity_y=>null() !< Y component of vector point from i,j to i+1,j+1 + ! (For detecting tri-polar fold) integer, dimension(:,:), pointer :: particle_counter_grd=>null() !< Counts particles created for naming purposes !>@{ !! Diagnostic handle @@ -65,11 +66,11 @@ module particles_types_mod real :: day !< Day of this record (days) real :: lat_old !< Previous latitude real :: lon_old !< Previous longitude - real :: uvel !< Zonal velocity of particle (m/s) + real :: uvel !< Zonal velocity of particle (m/s) real :: vvel !< Meridional velocity of particle (m/s) real :: uvel_old !< Previous zonal velocity component (m/s) real :: vvel_old !< Previous meridional velocity component (m/s) - integer :: year !< Year of this record + integer :: year !< Year of this record integer :: particle_num !< Current particle number integer(kind=8) :: id = -1 !< Particle Identifier type(xyt), pointer :: next=>null() !< Pointer to the next position in the list @@ -78,29 +79,29 @@ module particles_types_mod !>particle types are data structures describing a tracked particle type :: particle type(particle), pointer :: prev=>null() !< Previous link in list - type(particle), pointer :: next=>null() + type(particle), pointer :: next=>null() !< Next link in list ! State variables (specific to the particles, needed for restarts) real :: lon !< Longitude of particle (degree N or unit of grid coordinate) real :: lat !< Latitude of particle (degree E or unit of grid coordinate) real :: depth !< Depth of particle real :: uvel !< Zonal velocity of particle (m/s) real :: vvel !< Meridional velocity of particle (m/s) - real :: lon_old !< previous lon (degrees) - real :: lat_old !< previous lat (degrees) - real :: uvel_old !< previous uvel - real :: vvel_old !< previous vvel + real :: lon_old !< previous lon (degrees) + real :: lat_old !< previous lat (degrees) + real :: uvel_old !< previous uvel + real :: vvel_old !< previous vvel real :: start_lon !< starting longitude where particle was created real :: start_lat !< starting latitude where particle was created real :: start_day !< origination position (degrees) and day integer :: start_year !< origination year real :: halo_part !< equal to zero for particles on the computational domain, and 1 for particles on the halo - integer(kind=8) :: id !< particle identifier + integer(kind=8) :: id !< particle identifier integer(kind=8) :: drifter_num !< particle identifier - integer :: ine !< nearest i-index in NE direction (for convenience) + integer :: ine !< nearest i-index in NE direction (for convenience) integer :: jne !< nearest j-index in NE direction (for convenience) real :: xi !< non-dimensional x-coordinate within current cell (0..1) real :: yj !< non-dimensional y-coordinate within current cell (0..1) - real :: uo !< zonal ocean velocity + real :: uo !< zonal ocean velocity real :: vo !< meridional ocean velocity !< by the particle (m/s) type(xyt), pointer :: trajectory=>null() !< Trajectory for this particle @@ -141,7 +142,8 @@ module particles_types_mod logical :: halo_debugging=.False. !< Use for debugging halos (remove when its working) logical :: save_short_traj=.false. !< True saves only lon,lat,time,id in particle_trajectory.nc logical :: ignore_traj=.False. !< If true, then model does not write trajectory data at all - logical :: use_new_predictive_corrective =.False. !< Flag to use Bob's predictive corrective particle scheme- Added by Alon + logical :: use_new_predictive_corrective =.False. !< Flag to use Bob's predictive corrective particle scheme + !Added by Alon integer(kind=8) :: debug_particle_with_id = -1 !< If positive, monitors a part with this id type(buffer), pointer :: obuffer_n=>null() !< Buffer for outgoing parts to the north type(buffer), pointer :: ibuffer_n=>null() !< Buffer for incoming parts from the north From d8a1ceeb81d3dd0a6c30ca43bd3379e5427e2df0 Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Wed, 6 Oct 2021 11:10:03 -0500 Subject: [PATCH 09/13] converted pointers to allocatables in particles_gridded --- .../external/drifters/MOM_particles_types.F90 | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/config_src/external/drifters/MOM_particles_types.F90 b/config_src/external/drifters/MOM_particles_types.F90 index 80335f7656..3b37dc9d34 100644 --- a/config_src/external/drifters/MOM_particles_types.F90 +++ b/config_src/external/drifters/MOM_particles_types.F90 @@ -31,25 +31,25 @@ module particles_types_mod logical :: grid_is_latlon !< Flag to say whether the coordinate is in lat-lon degrees, or meters logical :: grid_is_regular !< Flag to say whether point in cell can be found assuming regular Cartesian grid real :: Lx !< Length of the domain in x direction - real, dimension(:,:), pointer :: lon=>null() !< Longitude of cell corners (degree E) - real, dimension(:,:), pointer :: lat=>null() !< Latitude of cell corners (degree N) - real, dimension(:,:), pointer :: lonc=>null() !< Longitude of cell centers (degree E) - real, dimension(:,:), pointer :: latc=>null() !< Latitude of cell centers (degree N) - real, dimension(:,:), pointer :: dx=>null() !< Length of cell edge (m) - real, dimension(:,:), pointer :: dy=>null() !< Length of cell edge (m) - real, dimension(:,:), pointer :: area=>null() !< Area of cell (m^2) - real, dimension(:,:), pointer :: msk=>null() !< Ocean-land mask (1=ocean) - real, dimension(:,:), pointer :: cos=>null() !< Cosine from rotation matrix to lat-lon coords - real, dimension(:,:), pointer :: sin=>null() !< Sine from rotation matrix to lat-lon coords - real, dimension(:,:), pointer :: ocean_depth=>NULL() !< Depth of ocean (m) - real, dimension(:,:), pointer :: uo=>null() !< Ocean zonal flow (m/s) - real, dimension(:,:), pointer :: vo=>null() !< Ocean meridional flow (m/s) - real, dimension(:,:), pointer :: tmp=>null() !< Temporary work space - real, dimension(:,:), pointer :: tmpc=>null() !< Temporary work space - real, dimension(:,:), pointer :: parity_x=>null() !< X component of vector point from i,j to i+1,j+1 - real, dimension(:,:), pointer :: parity_y=>null() !< Y component of vector point from i,j to i+1,j+1 + real, dimension(:,:), allocatable :: lon !< Longitude of cell corners (degree E) + real, dimension(:,:), allocatable :: lat !< Latitude of cell corners (degree N) + real, dimension(:,:), allocatable :: lonc !< Longitude of cell centers (degree E) + real, dimension(:,:), allocatable :: latc !< Latitude of cell centers (degree N) + real, dimension(:,:), allocatable :: dx !< Length of cell edge (m) + real, dimension(:,:), allocatable :: dy !< Length of cell edge (m) + real, dimension(:,:), allocatable :: area !< Area of cell (m^2) + real, dimension(:,:), allocatable :: msk !< Ocean-land mask (1=ocean) + real, dimension(:,:), allocatable :: cos !< Cosine from rotation matrix to lat-lon coords + real, dimension(:,:), allocatable :: sin !< Sine from rotation matrix to lat-lon coords + real, dimension(:,:), allocatable :: ocean_depth !< Depth of ocean (m) + real, dimension(:,:), allocatable :: uo !< Ocean zonal flow (m/s) + real, dimension(:,:), allocatable :: vo !< Ocean meridional flow (m/s) + real, dimension(:,:), allocatable :: tmp !< Temporary work space + real, dimension(:,:), allocatable :: tmpc !< Temporary work space + real, dimension(:,:), allocatable :: parity_x !< X component of vector point from i,j to i+1,j+1 + real, dimension(:,:), allocatable :: parity_y !< Y component of vector point from i,j to i+1,j+1 ! (For detecting tri-polar fold) - integer, dimension(:,:), pointer :: particle_counter_grd=>null() !< Counts particles created for naming purposes + integer, dimension(:,:), allocatable :: particle_counter_grd !< Counts particles created for naming purposes !>@{ !! Diagnostic handle integer :: id_uo=-1, id_vo=-1, id_unused=-1 From 653aa8cbc9d91b72ae8ee3165551522e3fcc30db Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Wed, 6 Oct 2021 11:37:24 -0500 Subject: [PATCH 10/13] Remove trailing space --- config_src/external/drifters/MOM_particles_types.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_src/external/drifters/MOM_particles_types.F90 b/config_src/external/drifters/MOM_particles_types.F90 index 3b37dc9d34..b7bc01acb9 100644 --- a/config_src/external/drifters/MOM_particles_types.F90 +++ b/config_src/external/drifters/MOM_particles_types.F90 @@ -79,7 +79,7 @@ module particles_types_mod !>particle types are data structures describing a tracked particle type :: particle type(particle), pointer :: prev=>null() !< Previous link in list - type(particle), pointer :: next=>null() !< Next link in list + type(particle), pointer :: next=>null() !< Next link in list ! State variables (specific to the particles, needed for restarts) real :: lon !< Longitude of particle (degree N or unit of grid coordinate) real :: lat !< Latitude of particle (degree E or unit of grid coordinate) From dcebb76742828870cfe62ca5f24271c37409c274 Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Wed, 6 Oct 2021 12:08:47 -0500 Subject: [PATCH 11/13] Further doxygen tweaks --- config_src/external/drifters/MOM_particles.F90 | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/config_src/external/drifters/MOM_particles.F90 b/config_src/external/drifters/MOM_particles.F90 index 1a7f603710..ceaa378da3 100644 --- a/config_src/external/drifters/MOM_particles.F90 +++ b/config_src/external/drifters/MOM_particles.F90 @@ -19,7 +19,8 @@ subroutine particles_init(parts, Grid, Time, dt, u, v) type(ocean_grid_type), target, intent(in) :: Grid !< Grid type from parent model type(time_type), intent(in) :: Time !< Time type from parent model real, intent(in) :: dt !< particle timestep in seconds - real, dimension(:,:,:),intent(in) :: u, v !< Horizontal velocity fields + real, dimension(:,:,:),intent(in) :: u !< Zonal velocity field + real, dimension(:,:,:),intent(in) :: v !< Meridional velocity field end subroutine particles_init @@ -32,7 +33,7 @@ subroutine particles_run(parts, time, uo, vo, ho, tv, stagger) real, dimension(:,:,:),intent(in) :: vo !< Ocean meridional velocity (m/s) real, dimension(:,:,:),intent(in) :: ho !< Ocean layer thickness [H ~> m or kg m-2] type(thermo_var_ptrs), intent(in) :: tv !< structure containing pointers to available thermodynamic fields - integer, optional, intent(in) :: stagger + integer, optional, intent(in) :: stagger !< Flag for whether velocities are staggered end subroutine particles_run @@ -40,16 +41,18 @@ end subroutine particles_run !>Save particle locations (and sometimes other vars) to restart file subroutine particles_save_restart(parts,temp,salt) ! Arguments -type(particles), pointer :: parts -real,dimension(:,:,:),optional,intent(in) :: temp, salt +type(particles), pointer :: parts !< Container for all types and memory +real,dimension(:,:,:),optional,intent(in) :: temp !< Optional container for temperature +real,dimension(:,:,:),optional,intent(in) :: salt !< Optional container for salinity end subroutine particles_save_restart !> Deallocate all memory and disassociated pointer subroutine particles_end(parts,temp,salt) ! Arguments -type(particles), pointer :: parts -real,dimension(:,:,:),optional,intent(in) :: temp, salt +type(particles), pointer :: parts !< Container for all types and memory +real,dimension(:,:,:),optional,intent(in) :: temp !< Optional container for temperature +real,dimension(:,:,:),optional,intent(in) :: salt !< Optional container for salinity end subroutine particles_end From 455db167c6ef133fe50e813259c85723861b2f2c Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Wed, 6 Oct 2021 12:18:33 -0500 Subject: [PATCH 12/13] another trailing space --- config_src/external/drifters/MOM_particles.F90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config_src/external/drifters/MOM_particles.F90 b/config_src/external/drifters/MOM_particles.F90 index ceaa378da3..135f5d284c 100644 --- a/config_src/external/drifters/MOM_particles.F90 +++ b/config_src/external/drifters/MOM_particles.F90 @@ -50,7 +50,7 @@ end subroutine particles_save_restart !> Deallocate all memory and disassociated pointer subroutine particles_end(parts,temp,salt) ! Arguments -type(particles), pointer :: parts !< Container for all types and memory +type(particles), pointer :: parts !< Container for all types and memory real,dimension(:,:,:),optional,intent(in) :: temp !< Optional container for temperature real,dimension(:,:,:),optional,intent(in) :: salt !< Optional container for salinity From 725d3fff4a19308f2e7864b2474fa60501c88054 Mon Sep 17 00:00:00 2001 From: Cory Spencer Jones Date: Mon, 11 Oct 2021 15:35:19 -0500 Subject: [PATCH 13/13] removed set_time --- src/core/MOM.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/MOM.F90 b/src/core/MOM.F90 index d1562aee59..73a7cd58a7 100644 --- a/src/core/MOM.F90 +++ b/src/core/MOM.F90 @@ -47,7 +47,6 @@ module MOM use MOM_time_manager, only : time_type, real_to_time, time_type_to_real, operator(+) use MOM_time_manager, only : operator(-), operator(>), operator(*), operator(/) use MOM_time_manager, only : operator(>=), operator(==), increment_date -use MOM_time_manager, only : set_time use MOM_unit_tests, only : unit_tests ! MOM core modules