Skip to content

Commit fd95dee

Browse files
committed
Allow some tracers to use a different advection scheme
This is a cleanup of tracer advection in preparation for adding higher order advection options in a subsequent pull request. All existing cases are bit for bit the same as before. Many of the tracer modules have code lines (exclusive of comments) of more than 100 characters. These have been edited for length in the modules updated here. Internally, TRACER_ADVECTION_SCHEME is now implmented as an integer lookup table, rather than as a set of logicals. Regional and OBC dye tracers can now be used in the same model run, provided the optional NUM_DYED_TRACERS is used in place of NUM_DYE_TRACERS for dyed_obc tracers with NUM_DYE_TRACERS then referring to the number of regional dye tracers. They can both now also go through their initialization code if they are not found in the restart files. For OBC dye tracers this requires TRACERS_MAY_REINIT=.true.. The new option to specify a different advection scheme for some passive tracers has been implemented for regional and OBC dye tracers. This is controlled by DYED_TRACER_ADVECTION_SCHEME for OBC dye tracers, and by DYExxx_TRACER_ADVECTION_SCHEME, where xxx is the 3 digit tracer number, for regional dye tracers. It is possible to test multiple advection schemes in the same model run by configuring multiple regional tracers with the same region but different advection schemes.
1 parent 792a061 commit fd95dee

File tree

7 files changed

+441
-250
lines changed

7 files changed

+441
-250
lines changed

src/tracer/MOM_tracer_advect.F90

Lines changed: 205 additions & 179 deletions
Large diffs are not rendered by default.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
!> This module contains constants for the tracer advection schemes.
2+
module MOM_tracer_advect_schemes
3+
4+
! This file is part of MOM6. See LICENSE.md for the license.
5+
6+
use MOM_error_handler, only : MOM_error, FATAL
7+
8+
implicit none ; public
9+
10+
! The following are public parameter constants
11+
integer, parameter :: ADVECT_PLM = 0 !< PLM advection scheme
12+
integer, parameter :: ADVECT_PPMH3 = 1 !< PPM:H3 advection scheme
13+
integer, parameter :: ADVECT_PPM = 2 !< PPM advection scheme
14+
15+
!> Documentation for tracer advection schemes
16+
character(len=*), parameter :: TracerAdvectionSchemeDoc = &
17+
" PLM - Piecewise Linear Method\n"//&
18+
" PPM:H3 - Piecewise Parabolic Method (Huyhn 3rd order)\n"// &
19+
" PPM - Piecewise Parabolic Method (Colella-Woodward)"
20+
21+
contains
22+
23+
!> Numeric value of tracer_advect_scheme corresponding to scheme name
24+
subroutine set_tracer_advect_scheme(scheme_value, advect_scheme_name)
25+
character(len=*), intent(in) :: advect_scheme_name !< Name of the advection scheme
26+
integer, intent(out) :: scheme_value !< Integer value of the advection scheme
27+
28+
select case (trim(advect_scheme_name))
29+
case ("")
30+
scheme_value = -1
31+
case ("PLM")
32+
scheme_value = ADVECT_PLM
33+
case ("PPM:H3")
34+
scheme_value = ADVECT_PPMH3
35+
case ("PPM")
36+
scheme_value = ADVECT_PPM
37+
case default
38+
call MOM_error(FATAL, "set_tracer_advect_scheme: "//&
39+
"Unknown TRACER_ADVECTION_SCHEME = "//trim(advect_scheme_name))
40+
end select
41+
end subroutine set_tracer_advect_scheme
42+
43+
end module MOM_tracer_advect_schemes

src/tracer/MOM_tracer_registry.F90

Lines changed: 87 additions & 43 deletions
Large diffs are not rendered by default.

src/tracer/MOM_tracer_types.F90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ module MOM_tracer_types
9999
! logical :: hordiff_tr = .true. !< If true, this tracer should experience epineutral diffusion
100100
! logical :: kpp_nonlocal_tr = .true. !< if true, apply KPP nonlocal transport to this tracer before diffusion
101101
logical :: remap_tr = .true. !< If true, this tracer should be vertically remapped
102+
integer :: advect_scheme = -1 ! flag for advection scheme
102103

103104
integer :: diag_form = 1 !< An integer indicating which template is to be used to label diagnostics.
104105
!>@{ Diagnostic IDs

src/tracer/dye_example.F90

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module regional_dyes
2424
use MOM_unit_scaling, only : unit_scale_type
2525
use MOM_variables, only : surface, thermo_var_ptrs
2626
use MOM_verticalGrid, only : verticalGrid_type
27+
use MOM_tracer_advect_schemes, only : set_tracer_advect_scheme, TracerAdvectionSchemeDoc
2728

2829
implicit none ; private
2930

@@ -63,7 +64,7 @@ module regional_dyes
6364
type(MOM_restart_CS), pointer :: restart_CSp => NULL() !< A pointer to the restart control structure
6465

6566
type(vardesc), allocatable :: tr_desc(:) !< Descriptions and metadata for the tracers
66-
logical :: tracers_may_reinit = .false. !< If true the tracers may be initialized if not found in a restart file
67+
logical :: tracers_may_reinit = .true. !< If true the tracers may be initialized if not found in a restart file
6768
end type dye_tracer_CS
6869

6970
contains
@@ -85,11 +86,15 @@ function register_dye_tracer(HI, GV, US, param_file, CS, tr_Reg, restart_CS)
8586
character(len=40) :: mdl = "regional_dyes" ! This module's name.
8687
character(len=48) :: var_name ! The variable's name.
8788
character(len=48) :: desc_name ! The variable's descriptor.
89+
character(len=48) :: param_name ! The param's name suffix.
8890
! This include declares and sets the variable "version".
8991
# include "version_variable.h"
9092
real, pointer :: tr_ptr(:,:,:) => NULL() ! A pointer to one of the tracers [CU ~> conc]
9193
logical :: register_dye_tracer
9294
integer :: isd, ied, jsd, jed, nz, m
95+
integer :: advect_scheme ! Advection scheme value for this tracer
96+
character(len=256) :: mesg ! Advection scheme name for this tracer
97+
9398
isd = HI%isd ; ied = HI%ied ; jsd = HI%jsd ; jed = HI%jed ; nz = GV%ke
9499

95100
if (associated(CS)) then
@@ -156,11 +161,19 @@ function register_dye_tracer(HI, GV, US, param_file, CS, tr_Reg, restart_CS)
156161
"This is the maximum depth at which we inject dyes.", &
157162
units="m", scale=US%m_to_Z, fail_if_missing=.true.)
158163
if (minval(CS%dye_source_maxdepth(:)) < -1.e29*US%m_to_Z) &
159-
call MOM_error(FATAL, "register_dye_tracer: Not enough values provided for DYE_SOURCE_MAXDEPTH ")
164+
call MOM_error(FATAL, "register_dye_tracer: Not enough values provided for DYE_SOURCE_MAXDEPTH")
160165

161166
allocate(CS%tr(isd:ied,jsd:jed,nz,CS%ntr), source=0.0)
162167

163168
do m = 1, CS%ntr
169+
write(param_name(:),'(A,I3.3,A)') "DYE",m,"_TRACER_ADVECTION_SCHEME"
170+
call get_param(param_file, mdl, trim(param_name), mesg, &
171+
desc="The horizontal transport scheme for dye tracer:\n"//&
172+
trim(TracerAdvectionSchemeDoc)//&
173+
"\n Set to blank (the default) to use TRACER_ADVECTION_SCHEME.", default="")
174+
! Get the integer value of the tracer scheme
175+
call set_tracer_advect_scheme(advect_scheme, mesg)
176+
164177
write(var_name(:),'(A,I3.3)') "dye",m
165178
write(desc_name(:),'(A,I3.3)') "Dye Tracer ",m
166179
CS%tr_desc(m) = var_desc(trim(var_name), "conc", trim(desc_name), caller=mdl)
@@ -173,7 +186,8 @@ function register_dye_tracer(HI, GV, US, param_file, CS, tr_Reg, restart_CS)
173186
! Register the tracer for horizontal advection, diffusion, and restarts.
174187
call register_tracer(tr_ptr, tr_Reg, param_file, HI, GV, &
175188
tr_desc=CS%tr_desc(m), registry_diags=.true., &
176-
restart_CS=restart_CS, mandatory=.not.CS%tracers_may_reinit)
189+
restart_CS=restart_CS, mandatory=.not.CS%tracers_may_reinit,&
190+
advect_scheme=advect_scheme)
177191

178192
! Set coupled_tracers to be true (hard-coded above) to provide the surface
179193
! values to the coupler (if any). This is meta-code and its arguments will
@@ -420,5 +434,8 @@ end subroutine regional_dyes_end
420434
!! are set to 1 within the geographical region specified. The depth
421435
!! which a tracer is set is determined by calculating the depth from
422436
!! the seafloor upwards through the column.
437+
!!
438+
!! The advection scheme of these tracers can be set to be different
439+
!! to that used by active tracers.
423440

424441
end module regional_dyes

src/tracer/dyed_obc_tracer.F90

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@ module dyed_obc_tracer
1313
use MOM_io, only : file_exists, MOM_read_data, slasher, vardesc, var_desc, query_vardesc
1414
use MOM_open_boundary, only : ocean_OBC_type
1515
use MOM_restart, only : MOM_restart_CS
16+
use MOM_restart, only : query_initialized, set_initialized
1617
use MOM_time_manager, only : time_type
1718
use MOM_tracer_registry, only : register_tracer, tracer_registry_type
1819
use MOM_tracer_diabatic, only : tracer_vertdiff, applyTracerBoundaryFluxesInOut
1920
use MOM_unit_scaling, only : unit_scale_type
2021
use MOM_variables, only : surface
2122
use MOM_verticalGrid, only : verticalGrid_type
23+
use MOM_open_boundary, only : OBC_segment_type, register_segment_tracer
24+
use MOM_tracer_registry, only : tracer_type
25+
use MOM_tracer_registry, only : tracer_name_lookup
26+
use MOM_tracer_advect_schemes, only : set_tracer_advect_scheme, TracerAdvectionSchemeDoc
2227

2328
implicit none ; private
2429

@@ -36,6 +41,9 @@ module dyed_obc_tracer
3641
type(tracer_registry_type), pointer :: tr_Reg => NULL() !< A pointer to the tracer registry
3742
real, pointer :: tr(:,:,:,:) => NULL() !< The array of tracers used in this subroutine in [conc]
3843

44+
logical :: tracers_may_reinit !< If true, these tracers be set up via the initialization code if
45+
!! they are not found in the restart files.
46+
3947
integer, allocatable, dimension(:) :: ind_tr !< Indices returned by atmos_ocn_coupler_flux if it is used and the
4048
!! surface tracer concentrations are to be provided to the coupler.
4149

@@ -69,6 +77,10 @@ function register_dyed_obc_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
6977
real, pointer :: tr_ptr(:,:,:) => NULL() ! The tracer concentration [conc]
7078
logical :: register_dyed_obc_tracer
7179
integer :: isd, ied, jsd, jed, nz, m
80+
integer :: n_dye ! Number of regionsl dye tracers
81+
integer :: advect_scheme ! Advection scheme value for this tracer
82+
character(len=256) :: mesg ! Advection scheme name for this tracer
83+
7284
isd = HI%isd ; ied = HI%ied ; jsd = HI%jsd ; jed = HI%jed ; nz = GV%ke
7385

7486
if (associated(CS)) then
@@ -79,9 +91,21 @@ function register_dyed_obc_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
7991

8092
! Read all relevant parameters and write them to the model log.
8193
call log_version(param_file, mdl, version, "")
82-
call get_param(param_file, mdl, "NUM_DYE_TRACERS", CS%ntr, &
83-
"The number of dye tracers in this run. Each tracer "//&
84-
"should have a separate boundary segment.", default=0)
94+
call get_param(param_file, mdl, "NUM_DYED_TRACERS", CS%ntr, &
95+
"The number of dyed_obc tracers in this run. Each tracer "//&
96+
"should have a separate boundary segment."//&
97+
"If not present, use NUM_DYE_TRACERS.", default=-1)
98+
if (CS%ntr == -1) then
99+
!for backward compatibility
100+
call get_param(param_file, mdl, "NUM_DYE_TRACERS", CS%ntr, &
101+
"The number of dye tracers in this run. Each tracer "//&
102+
"should have a separate boundary segment.", default=0)
103+
n_dye = 0
104+
else
105+
call get_param(param_file, mdl, "NUM_DYE_TRACERS", n_dye, &
106+
"The number of dye tracers in this run. Each tracer "//&
107+
"should have a separate region.", default=0, do_not_log=.true.)
108+
endif
85109
allocate(CS%ind_tr(CS%ntr))
86110
allocate(CS%tr_desc(CS%ntr))
87111

@@ -97,10 +121,21 @@ function register_dyed_obc_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
97121
CS%tracer_IC_file)
98122
endif
99123

124+
call get_param(param_file, mdl, "TRACERS_MAY_REINIT", CS%tracers_may_reinit, &
125+
"If true, tracers may go through the initialization code "//&
126+
"if they are not found in the restart files. Otherwise "//&
127+
"it is a fatal error if the tracers are not found in the "//&
128+
"restart files of a restarted run.", default=.false.)
129+
130+
call get_param(param_file, mdl, "DYED_TRACER_ADVECTION_SCHEME", mesg, &
131+
desc="The horizontal transport scheme for dyed_obc tracers:\n"//&
132+
trim(TracerAdvectionSchemeDoc)//&
133+
"\n Set to blank (the default) to use TRACER_ADVECTION_SCHEME.", default="")
134+
100135
allocate(CS%tr(isd:ied,jsd:jed,nz,CS%ntr), source=0.0)
101136

102137
do m=1,CS%ntr
103-
write(name,'("dye_",I2.2)') m
138+
write(name,'("dye_",I2.2)') m+n_dye !after regional dye tracers
104139
write(longname,'("Concentration of dyed_obc Tracer ",I2.2)') m
105140
CS%tr_desc(m) = var_desc(name, units="kg kg-1", longname=longname, caller=mdl)
106141
if (GV%Boussinesq) then ; flux_units = "kg kg-1 m3 s-1"
@@ -109,11 +144,14 @@ function register_dyed_obc_tracer(HI, GV, param_file, CS, tr_Reg, restart_CS)
109144
! This is needed to force the compiler not to do a copy in the registration
110145
! calls. Curses on the designers and implementers of Fortran90.
111146
tr_ptr => CS%tr(:,:,:,m)
147+
! Get the integer value of the tracer scheme
148+
call set_tracer_advect_scheme(advect_scheme, mesg)
112149
! Register the tracer for horizontal advection, diffusion, and restarts.
113150
call register_tracer(tr_ptr, tr_Reg, param_file, HI, GV, &
114151
name=name, longname=longname, units="kg kg-1", &
115152
registry_diags=.true., flux_units=flux_units, &
116-
restart_CS=restart_CS)
153+
restart_CS=restart_CS, mandatory=.not.CS%tracers_may_reinit, &
154+
advect_scheme=advect_scheme)
117155

118156
! Set coupled_tracers to be true (hard-coded above) to provide the surface
119157
! values to the coupler (if any). This is meta-code and its arguments will
@@ -158,24 +196,24 @@ subroutine initialize_dyed_obc_tracer(restart, day, G, GV, h, diag, OBC, CS)
158196
CS%Time => day
159197
CS%diag => diag
160198

161-
if (.not.restart) then
162-
if (len_trim(CS%tracer_IC_file) >= 1) then
163-
! Read the tracer concentrations from a netcdf file.
164-
if (.not.file_exists(CS%tracer_IC_file, G%Domain)) &
165-
call MOM_error(FATAL, "dyed_obc_initialize_tracer: Unable to open "// &
166-
CS%tracer_IC_file)
167-
do m=1,CS%ntr
199+
do m=1,CS%ntr
200+
if ((.not.restart) .or. (CS%tracers_may_reinit .and. .not. &
201+
query_initialized(CS%tr(:,:,:,m), name, CS%restart_CSp))) then
202+
if (len_trim(CS%tracer_IC_file) >= 1) then
203+
! Read the tracer concentrations from a netcdf file.
204+
if (.not.file_exists(CS%tracer_IC_file, G%Domain)) &
205+
call MOM_error(FATAL, "dyed_obc_initialize_tracer: Unable to open "// &
206+
CS%tracer_IC_file)
168207
call query_vardesc(CS%tr_desc(m), name, caller="initialize_dyed_obc_tracer")
169208
call MOM_read_data(CS%tracer_IC_file, trim(name), CS%tr(:,:,:,m), G%Domain)
170-
enddo
171-
else
172-
do m=1,CS%ntr
209+
else
173210
do k=1,nz ; do j=js,je ; do i=is,ie
174211
CS%tr(i,j,k,m) = 0.0
175212
enddo ; enddo ; enddo
176-
enddo
177-
endif
178-
endif ! restart
213+
endif
214+
call set_initialized(CS%tr(:,:,:,m), name, CS%restart_CSp)
215+
endif ! restart
216+
enddo ! Tracer loop
179217

180218
end subroutine initialize_dyed_obc_tracer
181219

@@ -264,5 +302,9 @@ end subroutine dyed_obc_tracer_end
264302
!! their output and the subroutine that does any tracer physics or
265303
!! chemistry along with diapycnal mixing (included here because some
266304
!! tracers may float or swim vertically or dye diapycnal processes).
305+
!!
306+
!! The advection scheme of these tracers can be set to be different
307+
!! to that used by active tracers.
308+
267309

268310
end module dyed_obc_tracer

src/user/dyed_obcs_initialization.F90

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
!> Dyed open boundary conditions
1+
!> Dyed open boundary conditions; OBC_USER_CONFIG="dyed_obcs"
22
module dyed_obcs_initialization
33

44
! This file is part of MOM6. See LICENSE.md for the license.
@@ -23,6 +23,7 @@ module dyed_obcs_initialization
2323

2424
integer :: ntr = 0 !< Number of dye tracers
2525
!! \todo This is a module variable. Move this variable into the control structure.
26+
real :: dye_obc_inflow = 0.0
2627

2728
contains
2829

@@ -36,11 +37,13 @@ subroutine dyed_obcs_set_OBC_data(OBC, G, GV, param_file, tr_Reg)
3637
type(param_file_type), intent(in) :: param_file !< A structure indicating the open file
3738
!! to parse for model parameter values.
3839
type(tracer_registry_type), pointer :: tr_Reg !< Tracer registry.
40+
3941
! Local variables
4042
character(len=40) :: mdl = "dyed_obcs_set_OBC_data" ! This subroutine's name.
4143
character(len=80) :: name, longname
4244
integer :: is, ie, js, je, isd, ied, jsd, jed, m, n, nz, ntr_id
4345
integer :: IsdB, IedB, JsdB, JedB
46+
integer :: n_dye ! Number of regionsl dye tracers
4447
real :: dye ! Inflow dye concentration [arbitrary]
4548
type(tracer_type), pointer :: tr_ptr => NULL()
4649

@@ -50,10 +53,25 @@ subroutine dyed_obcs_set_OBC_data(OBC, G, GV, param_file, tr_Reg)
5053

5154
if (.not.associated(OBC)) return
5255

53-
call get_param(param_file, mdl, "NUM_DYE_TRACERS", ntr, &
54-
"The number of dye tracers in this run. Each tracer "//&
55-
"should have a separate boundary segment.", default=0, &
56-
do_not_log=.true.)
56+
call get_param(param_file, mdl, "NUM_DYED_TRACERS", ntr, &
57+
"The number of dyed_obc tracers in this run. Each tracer "//&
58+
"should have a separate boundary segment."//&
59+
"If not present, use NUM_DYE_TRACERS.", default=-1, do_not_log=.true.)
60+
if (ntr == -1) then
61+
!for backward compatibility
62+
call get_param(param_file, mdl, "NUM_DYE_TRACERS", ntr, &
63+
"The number of dye tracers in this run. Each tracer "//&
64+
"should have a separate boundary segment.", default=0, do_not_log=.true.)
65+
n_dye = 0
66+
else
67+
call get_param(param_file, mdl, "NUM_DYE_TRACERS", n_dye, &
68+
"The number of dye tracers in this run. Each tracer "//&
69+
"should have a separate region.", default=0, do_not_log=.true.)
70+
endif
71+
72+
call get_param(param_file, mdl, "DYE_OBC_INFLOW", dye_obc_inflow, &
73+
"The OBC inflow value of dye tracers.", units="kg kg-1", &
74+
default=1.0)
5775

5876
if (OBC%number_of_segments < ntr) then
5977
call MOM_error(WARNING, "Error in dyed_obc segment setup")
@@ -63,13 +81,13 @@ subroutine dyed_obcs_set_OBC_data(OBC, G, GV, param_file, tr_Reg)
6381
! ! Set the inflow values of the dyes, one per segment.
6482
! ! We know the order: north, south, east, west
6583
do m=1,ntr
66-
write(name,'("dye_",I2.2)') m
84+
write(name,'("dye_",I2.2)') m+n_dye !after regional dye tracers
6785
write(longname,'("Concentration of dyed_obc Tracer ",I2.2, " on segment ",I2.2)') m, m
6886
call tracer_name_lookup(tr_Reg, ntr_id, tr_ptr, name)
6987

7088
do n=1,OBC%number_of_segments
7189
if (n == m) then
72-
dye = 1.0
90+
dye = dye_obc_inflow
7391
else
7492
dye = 0.0
7593
endif

0 commit comments

Comments
 (0)