@@ -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.
146147end 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