Skip to content

Commit 89067a3

Browse files
authored
User/wfc/nmme reproducibility 20250331 (#871)
* Update to allow reproducibility for NMME initialization runs. Uses DEFAULT_ANSWER_DATE <20190101 to reproduce forecast results from older executable. * Correcting trailing spaces. * (*) Update to allow for reproducibility of NMME results. Will change logfiles due to new parameter (REPRODUCE_2018_NMME_ANSWERS) being added. * Broke two lines into continuation lines due to length exceeding 132 characters previously. * Fixed trailing spaces
1 parent ad6f218 commit 89067a3

1 file changed

Lines changed: 42 additions & 19 deletions

File tree

src/ocean_data_assim/MOM_oda_driver.F90

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ module MOM_oda_driver_mod
143143
!! remapping invoked by the ODA driver. Values below 20190101 recover
144144
!! the answers from the end of 2018, while higher values use updated
145145
!! and more robust forms of the same expressions.
146+
logical :: reproduce_2018_nmme !< true if reproducing older NMME answers.
146147
end type ODA_CS
147148

148149

@@ -174,6 +175,8 @@ subroutine init_oda(Time, G, GV, US, diag_CS, CS)
174175
type(param_file_type) :: PF
175176
integer :: n
176177
integer :: isd, ied, jsd, jed
178+
integer :: is_oda, ie_oda, js_oda, je_oda
179+
integer :: isd_oda, ied_oda, jsd_oda, jed_oda
177180
integer, dimension(4) :: fld_sz
178181
character(len=32) :: assim_method
179182
integer :: npes_pm, ens_info(6)
@@ -257,6 +260,12 @@ subroutine init_oda(Time, G, GV, US, diag_CS, CS)
257260
"values use updated and more robust forms of the same expressions.", &
258261
default=default_answer_date, do_not_log=.not.GV%Boussinesq)
259262
if (.not.GV%Boussinesq) CS%answer_date = max(CS%answer_date, 20230701)
263+
264+
call get_param(PF, mdl, "REPRODUCE_2018_NMME_ANSWERS", CS%reproduce_2018_nmme, &
265+
"Logical flag needed to reproduce older NMME forecast answers."//&
266+
"True gives old answers, the default of false gives different answers.", &
267+
default=.false.)
268+
260269
inputdir = slasher(inputdir)
261270

262271
select case(lowercase(trim(assim_method)))
@@ -332,7 +341,7 @@ subroutine init_oda(Time, G, GV, US, diag_CS, CS)
332341

333342
h_neglect = set_h_neglect(GV, CS%answer_date, h_neglect_edge)
334343
call initialize_remapping(CS%remapCS, remap_scheme, om4_remap_via_sub_cells=om4_remap_via_sub_cells, &
335-
h_neglect=h_neglect, h_neglect_edge=h_neglect_edge)
344+
h_neglect=h_neglect, h_neglect_edge=h_neglect_edge, answer_date=CS%answer_date)
336345
call set_regrid_params(CS%regridCS, min_thickness=0.)
337346
isd = G%isd; ied = G%ied; jsd = G%jsd; jed = G%jed
338347

@@ -362,7 +371,9 @@ subroutine init_oda(Time, G, GV, US, diag_CS, CS)
362371
basin_file = trim(inputdir) // trim(basin_file)
363372
call get_param(PF, 'oda_driver', "BASIN_VAR", basin_var, &
364373
"The basin mask variable in BASIN_FILE.", default="basin")
365-
allocate(CS%oda_grid%basin_mask(isd:ied,jsd:jed), source=0.0)
374+
! Need different data domain indices for the ODA ensemble basin mask.
375+
call get_domain_extent(CS%Grid%Domain, is_oda, ie_oda, js_oda, je_oda, isd_oda, ied_oda, jsd_oda, jed_oda)
376+
allocate(CS%oda_grid%basin_mask(isd_oda:ied_oda,jsd_oda:jed_oda), source=0.0)
366377
call MOM_read_data(basin_file, basin_var, CS%oda_grid%basin_mask, CS%Grid%domain, timelevel=1)
367378
endif
368379

@@ -492,17 +503,16 @@ subroutine get_posterior_tracer(Time, CS, increment)
492503
if (present(increment)) get_inc = increment
493504

494505
if (get_inc) then
495-
allocate(Ocean_increment)
496-
Ocean_increment%T = CS%Ocean_posterior%T - CS%Ocean_prior%T
497-
Ocean_increment%S = CS%Ocean_posterior%S - CS%Ocean_prior%S
506+
CS%Ocean_increment%T = CS%Ocean_posterior%T - CS%Ocean_prior%T
507+
CS%Ocean_increment%S = CS%Ocean_posterior%S - CS%Ocean_prior%S
498508
endif
499509
! It may be necessary to check whether the increment and ocean state have the
500510
! same dimensionally rescaled units.
501511
do m=1,CS%ensemble_size
502512
if (get_inc) then
503-
call redistribute_array(CS%mpp_domain, Ocean_increment%T(:,:,:,m),&
513+
call redistribute_array(CS%mpp_domain, CS%Ocean_increment%T(:,:,:,m),&
504514
CS%domains(m)%mpp_domain, CS%T_tend, complete=.true.)
505-
call redistribute_array(CS%mpp_domain, Ocean_increment%S(:,:,:,m),&
515+
call redistribute_array(CS%mpp_domain, CS%Ocean_increment%S(:,:,:,m),&
506516
CS%domains(m)%mpp_domain, CS%S_tend, complete=.true.)
507517
else
508518
call redistribute_array(CS%mpp_domain, CS%Ocean_posterior%T(:,:,:,m),&
@@ -568,25 +578,38 @@ subroutine get_bias_correction_tracer(Time, US, CS)
568578

569579
call cpu_clock_begin(id_clock_bias_adjustment)
570580
call horiz_interp_and_extrap_tracer(CS%INC_CS%T, Time, CS%G, T_bias, &
571-
valid_flag, z_in, z_edges_in, missing_value, scale=US%degC_to_C*US%s_to_T, spongeOngrid=.true.)
581+
valid_flag, z_in, z_edges_in, missing_value, scale=US%degC_to_C*US%s_to_T, spongeOngrid=.true., &
582+
answer_date=CS%answer_date)
572583
call horiz_interp_and_extrap_tracer(CS%INC_CS%S, Time, CS%G, S_bias, &
573-
valid_flag, z_in, z_edges_in, missing_value, scale=US%ppt_to_S*US%s_to_T, spongeOngrid=.true.)
584+
valid_flag, z_in, z_edges_in, missing_value, scale=US%ppt_to_S*US%s_to_T, spongeOngrid=.true., &
585+
answer_date=CS%answer_date)
574586

575587
! This should be replaced to use mask_z instead of the following lines
576588
! which are intended to zero land values using an arbitrary limit.
577589
fld_sz=shape(T_bias)
578-
do i=1,fld_sz(1)
579-
do j=1,fld_sz(2)
580-
do k=1,fld_sz(3)
581-
! if (T_bias(i,j,k) > 1.0E-3*US%degC_to_C) T_bias(i,j,k) = 0.0
582-
! if (S_bias(i,j,k) > 1.0E-3*US%ppt_to_S) S_bias(i,j,k) = 0.0
583-
if (valid_flag(i,j,k)==0.) then
584-
T_bias(i,j,k)=0.0
585-
S_bias(i,j,k)=0.0
586-
endif
590+
if (CS%reproduce_2018_nmme) then
591+
do i=1,fld_sz(1)
592+
do j=1,fld_sz(2)
593+
do k=1,fld_sz(3)
594+
! The following two lines are needed for backward compatibility for NMME answers (2018 vintage)
595+
! These were implemented to catch missing values, so large values are excluded.
596+
if (T_bias(i,j,k) > 1.0E-3*US%degC_to_C) T_bias(i,j,k) = 0.0
597+
if (S_bias(i,j,k) > 1.0E-3*US%ppt_to_S) S_bias(i,j,k) = 0.0
598+
enddo
587599
enddo
588600
enddo
589-
enddo
601+
else
602+
do i=1,fld_sz(1)
603+
do j=1,fld_sz(2)
604+
do k=1,fld_sz(3)
605+
if (valid_flag(i,j,k)==0.) then
606+
T_bias(i,j,k)=0.0
607+
S_bias(i,j,k)=0.0
608+
endif
609+
enddo
610+
enddo
611+
enddo
612+
endif
590613

591614
CS%T_bc_tend = T_bias * CS%bias_adjustment_multiplier
592615
CS%S_bc_tend = S_bias * CS%bias_adjustment_multiplier

0 commit comments

Comments
 (0)