@@ -48,6 +48,9 @@ module MOM_open_boundary
4848public open_boundary_test_extern_uv
4949public open_boundary_test_extern_h
5050public open_boundary_zero_normal_flow
51+ public parse_segment_str
52+ public parse_segment_manifest_str
53+ public parse_segment_data_str
5154public register_OBC, OBC_registry_init
5255public register_file_OBC, file_OBC_end
5356public segment_tracer_registry_init
@@ -61,12 +64,10 @@ module MOM_open_boundary
6164public rotate_OBC_config
6265public rotate_OBC_init
6366public initialize_segment_data
67+ public flood_fill
68+ public flood_fill2
6469
6570integer , parameter , public :: OBC_NONE = 0 ! < Indicates the use of no open boundary
66- integer , parameter , public :: OBC_SIMPLE = 1 ! < Indicates the use of a simple inflow open boundary
67- integer , parameter , public :: OBC_WALL = 2 ! < Indicates the use of a closed wall
68- integer , parameter , public :: OBC_FLATHER = 3 ! < Indicates the use of a Flather open boundary
69- integer , parameter , public :: OBC_RADIATION = 4 ! < Indicates the use of a radiation open boundary
7071integer , parameter , public :: OBC_DIRECTION_N = 100 ! < Indicates the boundary is an effective northern boundary
7172integer , parameter , public :: OBC_DIRECTION_S = 200 ! < Indicates the boundary is an effective southern boundary
7273integer , parameter , public :: OBC_DIRECTION_E = 300 ! < Indicates the boundary is an effective eastern boundary
@@ -310,6 +311,9 @@ module MOM_open_boundary
310311 real :: ramp_value ! < If ramp is True, where we are on the ramp from
311312 ! ! zero to one [nondim].
312313 type (time_type) :: ramp_start_time ! < Time when model was started.
314+ logical :: answers_2018 ! < If true, use the order of arithmetic and expressions for remapping
315+ ! ! that recover the answers from the end of 2018. Otherwise, use more
316+ ! ! robust and accurate forms of mathematically equivalent expressions.
313317end type ocean_OBC_type
314318
315319! > Control structure for open boundaries that read from files.
@@ -607,15 +611,15 @@ subroutine open_boundary_config(G, US, param_file, OBC)
607611 call get_param(param_file, mdl, " DEFAULT_2018_ANSWERS" , default_2018_answers, &
608612 " This sets the default value for the various _2018_ANSWERS parameters." , &
609613 default= .false. )
610- call get_param(param_file, mdl, " REMAPPING_2018_ANSWERS" , answers_2018, &
614+ call get_param(param_file, mdl, " REMAPPING_2018_ANSWERS" , OBC % answers_2018, &
611615 " If true, use the order of arithmetic and expressions that recover the " // &
612616 " answers from the end of 2018. Otherwise, use updated and more robust " // &
613617 " forms of the same expressions." , default= default_2018_answers)
614618
615619 allocate (OBC% remap_CS)
616620 call initialize_remapping(OBC% remap_CS, remappingScheme, boundary_extrapolation = .false. , &
617621 check_reconstruction= check_reconstruction, check_remapping= check_remapping, &
618- force_bounds_in_subcell= force_bounds_in_subcell, answers_2018= answers_2018)
622+ force_bounds_in_subcell= force_bounds_in_subcell, answers_2018= OBC % answers_2018)
619623
620624 endif ! OBC%number_of_segments > 0
621625
@@ -1693,88 +1697,6 @@ subroutine parse_for_tracer_reservoirs(OBC, PF, use_temperature)
16931697
16941698end subroutine parse_for_tracer_reservoirs
16951699
1696- ! > Parse an OBC_SEGMENT_%%%_PARAMS string
1697- subroutine parse_segment_param_real (segment_str , var , param_value , debug )
1698- character (len=* ), intent (in ) :: segment_str ! < A string in form of
1699- ! ! "VAR1=file:foo1.nc(varnam1),VAR2=file:foo2.nc(varnam2),..."
1700- character (len=* ), intent (in ) :: var ! < The name of the variable for which parameters are needed
1701- real , intent (out ) :: param_value ! < The value of the parameter
1702- logical , optional , intent (in ) :: debug ! < If present and true, write verbose debugging messages
1703- ! Local variables
1704- character (len= 128 ) :: word1, word2, word3, method
1705- integer :: lword, nfields, n, m
1706- logical :: continue ,dbg
1707- character (len= 32 ), dimension (MAX_OBC_FIELDS) :: flds
1708-
1709- nfields = 0
1710- continue = .true.
1711- dbg = .false.
1712- if (PRESENT (debug)) dbg = debug
1713-
1714- do while (continue )
1715- word1 = extract_word(segment_str,' ,' ,nfields+1 )
1716- if (trim (word1) == ' ' ) exit
1717- nfields = nfields+1
1718- word2 = extract_word(word1,' =' ,1 )
1719- flds(nfields) = trim (word2)
1720- enddo
1721-
1722- ! if (PRESENT(fields)) then
1723- ! do n=1,nfields
1724- ! fields(n) = flds(n)
1725- ! enddo
1726- ! endif
1727-
1728- ! if (PRESENT(num_fields)) then
1729- ! num_fields = nfields
1730- ! return
1731- ! endif
1732-
1733- m= 0
1734- ! if (PRESENT(var)) then
1735- do n= 1 ,nfields
1736- if (trim (var)==trim (flds(n))) then
1737- m = n
1738- exit
1739- endif
1740- enddo
1741- if (m== 0 ) then
1742- error stop
1743- endif
1744-
1745- ! Process first word which will start with the fieldname
1746- word3 = extract_word(segment_str,' ,' ,m)
1747- ! word1 = extract_word(word3,':',1)
1748- ! if (trim(word1) == '') exit
1749- word2 = extract_word(word1,' =' ,1 )
1750- if (trim (word2) == trim (var)) then
1751- method= trim (extract_word(word1,' =' ,2 ))
1752- lword= len_trim (method)
1753- read (method(1 :lword),* ,err= 987 ) param_value
1754- ! if (method(lword-3:lword) == 'file') then
1755- ! ! raise an error id filename/fieldname not in argument list
1756- ! word1 = extract_word(word3,':',2)
1757- ! filenam = extract_word(word1,'(',1)
1758- ! fieldnam = extract_word(word1,'(',2)
1759- ! lword=len_trim(fieldnam)
1760- ! fieldnam = fieldnam(1:lword-1) ! remove trailing parenth
1761- ! value=-999.
1762- ! elseif (method(lword-4:lword) == 'value') then
1763- ! filenam = 'none'
1764- ! fieldnam = 'none'
1765- ! word1 = extract_word(word3,':',2)
1766- ! lword=len_trim(word1)
1767- ! read(word1(1:lword),*,end=986,err=987) value
1768- ! endif
1769- endif
1770- ! endif
1771-
1772- return
1773- 986 call MOM_error(FATAL,' End of record while parsing segment data specification! ' // trim (segment_str))
1774- 987 call MOM_error(FATAL,' Error while parsing segment parameter specification! ' // trim (segment_str))
1775-
1776- end subroutine parse_segment_param_real
1777-
17781700! > Initialize open boundary control structure and do any necessary rescaling of OBC
17791701! ! fields that have been read from a restart file.
17801702subroutine open_boundary_init (G , GV , US , param_file , OBC , restart_CS )
@@ -3722,6 +3644,7 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
37223644 real , allocatable :: normal_trans_bt(:,:) ! barotropic transport [H L2 T-1 ~> m3 s-1]
37233645 integer :: turns ! Number of index quarter turns
37243646 real :: time_delta ! Time since tidal reference date [T ~> s]
3647+ real :: h_neglect, h_neglect_edge ! Small thicknesses [H ~> m or kg m-2]
37253648
37263649 is = G% isc ; ie = G% iec ; js = G% jsc ; je = G% jec
37273650 isd = G% isd ; ied = G% ied ; jsd = G% jsd ; jed = G% jed
@@ -3734,6 +3657,14 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
37343657
37353658 if (OBC% add_tide_constituents) time_delta = US% s_to_T * time_type_to_real(Time - OBC% time_ref)
37363659
3660+ if (.not. OBC% answers_2018) then
3661+ h_neglect = GV% H_subroundoff ; h_neglect_edge = GV% H_subroundoff
3662+ elseif (GV% Boussinesq) then
3663+ h_neglect = GV% m_to_H * 1.0e-30 ; h_neglect_edge = GV% m_to_H * 1.0e-10
3664+ else
3665+ h_neglect = GV% kg_m2_to_H * 1.0e-30 ; h_neglect_edge = GV% kg_m2_to_H * 1.0e-10
3666+ endif
3667+
37373668 do n = 1 , OBC% number_of_segments
37383669 segment = > OBC% segment(n)
37393670
@@ -3932,7 +3863,8 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
39323863 ! no dz for tidal variables
39333864 if (segment% field(m)% nk_src > 1 .and. &
39343865 (index (segment% field(m)% name, ' phase' ) <= 0 .and. index (segment% field(m)% name, ' amp' ) <= 0 )) then
3935- call time_interp_external(segment% field(m)% fid_dz,Time, tmp_buffer_in)
3866+ call time_interp_external(segment% field(m)% fid_dz, Time, tmp_buffer_in)
3867+ tmp_buffer_in(:,:,:) = tmp_buffer_in(:,:,:) * US% m_to_Z
39363868 if (turns /= 0 ) then
39373869 ! TODO: This is hardcoded for 90 degrees, and needs to be generalized.
39383870 if (segment% is_E_or_W &
@@ -3998,19 +3930,22 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
39983930 call remapping_core_h(OBC% remap_CS, &
39993931 segment% field(m)% nk_src,segment% field(m)% dz_src(I,J,:), &
40003932 segment% field(m)% buffer_src(I,J,:), &
4001- GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:))
3933+ GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:), &
3934+ h_neglect, h_neglect_edge)
40023935 elseif (G% mask2dCu(I,j)>0 .) then
40033936 h_stack(:) = h(i+ ishift,j,:)
40043937 call remapping_core_h(OBC% remap_CS, &
40053938 segment% field(m)% nk_src,segment% field(m)% dz_src(I,J,:), &
40063939 segment% field(m)% buffer_src(I,J,:), &
4007- GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:))
3940+ GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:), &
3941+ h_neglect, h_neglect_edge)
40083942 elseif (G% mask2dCu(I,j+1 )>0 .) then
40093943 h_stack(:) = h(i+ ishift,j+1 ,:)
40103944 call remapping_core_h(OBC% remap_CS, &
40113945 segment% field(m)% nk_src,segment% field(m)% dz_src(I,j,:), &
40123946 segment% field(m)% buffer_src(I,J,:), &
4013- GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:))
3947+ GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:), &
3948+ h_neglect, h_neglect_edge)
40143949 endif
40153950 enddo
40163951 else
@@ -4025,7 +3960,8 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
40253960 call remapping_core_h(OBC% remap_CS, &
40263961 segment% field(m)% nk_src, scl_fac* segment% field(m)% dz_src(I,j,:), &
40273962 segment% field(m)% buffer_src(I,j,:), &
4028- GV% ke, h(i+ ishift,j,:), segment% field(m)% buffer_dst(I,j,:))
3963+ GV% ke, h(i+ ishift,j,:), segment% field(m)% buffer_dst(I,j,:), &
3964+ h_neglect, h_neglect_edge)
40293965 endif
40303966 enddo
40313967 endif
@@ -4044,19 +3980,22 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
40443980 call remapping_core_h(OBC% remap_CS, &
40453981 segment% field(m)% nk_src,segment% field(m)% dz_src(I,J,:), &
40463982 segment% field(m)% buffer_src(I,J,:), &
4047- GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:))
3983+ GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:), &
3984+ h_neglect, h_neglect_edge)
40483985 elseif (G% mask2dCv(i,J)>0 .) then
40493986 h_stack(:) = h(i,j+ jshift,:)
40503987 call remapping_core_h(OBC% remap_CS, &
40513988 segment% field(m)% nk_src,segment% field(m)% dz_src(I,J,:), &
40523989 segment% field(m)% buffer_src(I,J,:), &
4053- GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:))
3990+ GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:), &
3991+ h_neglect, h_neglect_edge)
40543992 elseif (G% mask2dCv(i+1 ,J)>0 .) then
40553993 h_stack(:) = h(i+1 ,j+ jshift,:)
40563994 call remapping_core_h(OBC% remap_CS, &
40573995 segment% field(m)% nk_src,segment% field(m)% dz_src(I,J,:), &
40583996 segment% field(m)% buffer_src(I,J,:), &
4059- GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:))
3997+ GV% ke, h_stack, segment% field(m)% buffer_dst(I,J,:), &
3998+ h_neglect, h_neglect_edge)
40603999 endif
40614000 enddo
40624001 else
@@ -4071,7 +4010,8 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
40714010 call remapping_core_h(OBC% remap_CS, &
40724011 segment% field(m)% nk_src, scl_fac* segment% field(m)% dz_src(i,J,:), &
40734012 segment% field(m)% buffer_src(i,J,:), &
4074- GV% ke, h(i,j+ jshift,:), segment% field(m)% buffer_dst(i,J,:))
4013+ GV% ke, h(i,j+ jshift,:), segment% field(m)% buffer_dst(i,J,:), &
4014+ h_neglect, h_neglect_edge)
40754015 endif
40764016 enddo
40774017 endif
0 commit comments