Skip to content

Commit

Permalink
Merge pull request mom-ocean#1078 from Hallberg-NOAA/more_cleanup
Browse files Browse the repository at this point in the history
MOM6: +Additional code cleanup
  • Loading branch information
marshallward authored Mar 20, 2020
2 parents b8afb90 + a99e444 commit 02f257b
Show file tree
Hide file tree
Showing 17 changed files with 54 additions and 57 deletions.
4 changes: 2 additions & 2 deletions src/ALE/MOM_regridding.F90
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ subroutine initialize_regridding(CS, GV, US, max_depth, param_file, mdl, coord_m
call get_param(param_file, mdl, "HALOCLINE_FILTER_LENGTH", filt_len, &
"A length scale over which to smooth the temperature and "//&
"salinity before identifying erroneously unstable haloclines.", &
units="m", default=2.0)
units="m", default=2.0, scale=GV%m_to_H)
call get_param(param_file, mdl, "HALOCLINE_STRAT_TOL", strat_tol, &
"A tolerance for the ratio of the stratification of the "//&
"apparent coordinate stratification to the actual value "//&
Expand Down Expand Up @@ -2247,7 +2247,7 @@ subroutine set_regrid_params( CS, boundary_extrapolation, min_thickness, old_gri
!! resolved stratification [nondim]
logical, optional, intent(in) :: fix_haloclines !< Detect regions with much weaker stratification in the coordinate
real, optional, intent(in) :: halocline_filt_len !< Length scale over which to filter T & S when looking for
!! spuriously unstable water mass profiles [m]
!! spuriously unstable water mass profiles [H ~> m or kg m-2]
real, optional, intent(in) :: halocline_strat_tol !< Value of the stratification ratio that defines a problematic
!! halocline region.
logical, optional, intent(in) :: integrate_downward_for_e !< If true, integrate for interface positions downward
Expand Down
12 changes: 5 additions & 7 deletions src/core/MOM.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1542,10 +1542,9 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, &
integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed, nz
integer :: IsdB, IedB, JsdB, JedB
real :: dtbt ! The barotropic timestep [s]
real :: Z_diag_int ! minimum interval between calc depth-space diagnosetics [s]

real, allocatable, dimension(:,:) :: eta ! free surface height or column mass [H ~> m or kg m-2]
real, allocatable, dimension(:,:) :: area_shelf_h ! area occupied by ice shelf [m2]
real, allocatable, dimension(:,:) :: area_shelf_h ! area occupied by ice shelf [L2 ~> m2]
real, dimension(:,:), allocatable, target :: frac_shelf_h ! fraction of total area occupied by ice shelf [nondim]
real, dimension(:,:), pointer :: shelf_area => NULL()
type(MOM_restart_CS), pointer :: restart_CSp_tmp => NULL()
Expand Down Expand Up @@ -1975,7 +1974,6 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, &

call verticalGridInit( param_file, CS%GV, US )
GV => CS%GV
! dG%g_Earth = GV%mks_g_Earth

! Allocate the auxiliary non-symmetric domain for debugging or I/O purposes.
if (CS%debug .or. dG%symmetric) &
Expand Down Expand Up @@ -2172,7 +2170,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, &
else ; G%Domain_aux => G%Domain ; endif
! Copy common variables from the vertical grid to the horizontal grid.
! Consider removing this later?
G%ke = GV%ke ; G%g_Earth = GV%mks_g_Earth
G%ke = GV%ke

call MOM_initialize_state(CS%u, CS%v, CS%h, CS%tv, Time, G, GV, US, param_file, &
dirs, restart_CSp, CS%ALE_CSp, CS%tracer_Reg, &
Expand Down Expand Up @@ -2208,7 +2206,7 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, &
if (CS%debug .or. CS%G%symmetric) then
call clone_MOM_domain(CS%G%Domain, CS%G%Domain_aux, symmetric=.false.)
else ; CS%G%Domain_aux => CS%G%Domain ;endif
G%ke = GV%ke ; G%g_Earth = GV%mks_g_Earth
G%ke = GV%ke
endif

! At this point, all user-modified initialization code has been called. The
Expand All @@ -2234,13 +2232,13 @@ subroutine initialize_MOM(Time, Time_init, param_file, dirs, CS, restart_CSp, &

allocate(area_shelf_h(isd:ied,jsd:jed))
allocate(frac_shelf_h(isd:ied,jsd:jed))
call MOM_read_data(filename, trim(area_varname), area_shelf_h, G%Domain)
call MOM_read_data(filename, trim(area_varname), area_shelf_h, G%Domain, scale=US%m_to_L**2)
! initialize frac_shelf_h with zeros (open water everywhere)
frac_shelf_h(:,:) = 0.0
! compute fractional ice shelf coverage of h
do j=jsd,jed ; do i=isd,ied
if (G%areaT(i,j) > 0.0) &
frac_shelf_h(i,j) = area_shelf_h(i,j) / (US%L_to_m**2*G%areaT(i,j))
frac_shelf_h(i,j) = area_shelf_h(i,j) / G%areaT(i,j)
enddo ; enddo
! pass to the pointer
shelf_area => frac_shelf_h
Expand Down
2 changes: 0 additions & 2 deletions src/core/MOM_barotropic.F90
Original file line number Diff line number Diff line change
Expand Up @@ -2540,9 +2540,7 @@ subroutine apply_velocity_OBCs(OBC, ubt, vbt, uhbt, vhbt, ubt_trans, vbt_trans,
integer :: i, j, is, ie, js, je
real, dimension(SZIB_(G),SZJB_(G)) :: grad
real, parameter :: eps = 1.0e-20
real :: rx_max, ry_max ! coefficients for radiation
is = G%isc-halo ; ie = G%iec+halo ; js = G%jsc-halo ; je = G%jec+halo
rx_max = OBC%rx_max ; ry_max = OBC%rx_max

if (BT_OBC%apply_u_OBCs) then
do j=js,je ; do I=is-1,ie ; if (OBC%segnum_u(I,j) /= OBC_NONE) then
Expand Down
2 changes: 1 addition & 1 deletion src/core/MOM_forcing_type.F90
Original file line number Diff line number Diff line change
Expand Up @@ -2252,7 +2252,7 @@ subroutine forcing_diagnostics(fluxes, sfc_state, G, US, time_end, diag, handles
real, dimension(SZI_(G),SZJ_(G)) :: res
real :: total_transport ! for diagnosing integrated boundary transport
real :: ave_flux ! for diagnosing averaged boundary flux
real :: C_p ! seawater heat capacity (J/(deg K * kg))
real :: C_p ! seawater heat capacity [J degC-1 kg-1]
real :: RZ_T_conversion ! A combination of scaling factors for mass fluxes [kg T m-2 s-1 R-1 Z-1 ~> 1]
real :: I_dt ! inverse time step [s-1]
real :: ppt2mks ! conversion between ppt and mks
Expand Down
1 change: 0 additions & 1 deletion src/core/MOM_grid.F90
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ module MOM_grid
real ALLOCABLE_, dimension(NIMEM_,NJMEM_) :: &
df_dx, & !< Derivative d/dx f (Coriolis parameter) at h-points [T-1 L-1 ~> s-1 m-1].
df_dy !< Derivative d/dy f (Coriolis parameter) at h-points [T-1 L-1 ~> s-1 m-1].
real :: g_Earth !< The gravitational acceleration [m2 Z-1 s-2 ~> m s-2].

! These variables are global sums that are useful for 1-d diagnostics and should not be rescaled.
real :: areaT_global !< Global sum of h-cell area [m2]
Expand Down
4 changes: 2 additions & 2 deletions src/core/MOM_interface_heights.F90
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ subroutine find_eta_3d(h, tv, G, GV, US, eta, eta_bt, halo_size, eta_to_m)
!! the units of eta to m; by default this is US%Z_to_m.

! Local variables
real :: p(SZI_(G),SZJ_(G),SZK_(G)+1)
real :: p(SZI_(G),SZJ_(G),SZK_(G)+1) ! Hydrostatic pressure at each interface [Pa]
real :: dz_geo(SZI_(G),SZJ_(G),SZK_(G)) ! The change in geopotential height
! across a layer [m2 s-2].
real :: dilate(SZI_(G)) ! non-dimensional dilation factor
real :: htot(SZI_(G)) ! total thickness H
real :: htot(SZI_(G)) ! total thickness [H ~> m or kg m-2]
real :: I_gEarth
real :: Z_to_eta, H_to_eta, H_to_rho_eta ! Unit conversion factors with obvious names.
integer i, j, k, isv, iev, jsv, jev, nz, halo
Expand Down
13 changes: 8 additions & 5 deletions src/core/MOM_open_boundary.F90
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ module MOM_open_boundary
real, pointer, dimension(:,:,:) :: buffer_src=>NULL() !< buffer for segment data located at cell faces
!! and on the original vertical grid
integer :: nk_src !< Number of vertical levels in the source data
real, dimension(:,:,:), pointer :: dz_src=>NULL() !< vertical grid cell spacing of the incoming segment data [m]
real, dimension(:,:,:), pointer :: dz_src=>NULL() !< vertical grid cell spacing of the incoming segment
!! data, set in [Z ~> m] then scaled to [H ~> m or kg m-2]
real, dimension(:,:,:), pointer :: buffer_dst=>NULL() !< buffer src data remapped to the target vertical grid
real, dimension(:,:), pointer :: bt_vel=>NULL() !< barotropic velocity [L T-1 ~> m s-1]
real :: value !< constant value if fid is equal to -1
Expand Down Expand Up @@ -260,6 +261,7 @@ module MOM_open_boundary
real :: rx_max !< The maximum magnitude of the baroclinic radiation
!! velocity (or speed of characteristics) [m s-1]. The
!! default value is 10 m s-1.
!### The description above seems inconsistent with the code, and the units should be [nondim].
logical :: OBC_pe !< Is there an open boundary on this tile?
type(remapping_CS), pointer :: remap_CS !< ALE remapping control structure for segments only
type(OBC_registry_type), pointer :: OBC_Reg => NULL() !< Registry type for boundaries
Expand Down Expand Up @@ -478,11 +480,13 @@ subroutine open_boundary_config(G, US, param_file, OBC)
call initialize_segment_data(G, OBC, param_file)

if (open_boundary_query(OBC, apply_open_OBC=.true.)) then
!### I think that OBC%rx_max as used is actually nondimensional, with effective
! units of grid points per time step.
call get_param(param_file, mdl, "OBC_RADIATION_MAX", OBC%rx_max, &
"The maximum magnitude of the baroclinic radiation "//&
"velocity (or speed of characteristics). This is only "//&
"used if one of the open boundary segments is using Orlanski.", &
units="m s-1", default=10.0)
units="m s-1", default=10.0) !### Should the units here be "nondim"?
call get_param(param_file, mdl, "OBC_RAD_VEL_WT", OBC%gamma_uv, &
"The relative weighting for the baroclinic radiation "//&
"velocities (or speed of characteristics) at the new "//&
Expand Down Expand Up @@ -3421,16 +3425,15 @@ subroutine update_OBC_segment_data(G, GV, US, OBC, tv, h, Time)
type(unit_scale_type), intent(in) :: US !< A dimensional unit scaling type
type(ocean_OBC_type), pointer :: OBC !< Open boundary structure
type(thermo_var_ptrs), intent(in) :: tv !< Thermodynamics structure
real, dimension(SZI_(G),SZJ_(G), SZK_(G)), intent(inout) :: h !< Thickness [m]
real, dimension(SZI_(G),SZJ_(G), SZK_(G)), intent(inout) :: h !< Thickness [H ~> m or kg m-2]
type(time_type), intent(in) :: Time !< Model time
! Local variables
integer :: i, j, k, is, ie, js, je, isd, ied, jsd, jed
integer :: IsdB, IedB, JsdB, JedB, n, m, nz
character(len=40) :: mdl = "set_OBC_segment_data" ! This subroutine's name.
character(len=200) :: filename, OBC_file, inputdir ! Strings for file/path
type(OBC_segment_type), pointer :: segment => NULL()
integer, dimension(4) :: siz,siz2
real :: sumh ! column sum of thicknesses [m]
integer, dimension(4) :: siz
integer :: ni_seg, nj_seg ! number of src gridpoints along the segments
integer :: i2, j2 ! indices for referencing local domain array
integer :: is_obc, ie_obc, js_obc, je_obc ! segment indices within local domain
Expand Down
37 changes: 19 additions & 18 deletions src/initialization/MOM_state_initialization.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1009,9 +1009,9 @@ subroutine depress_surface(h, G, GV, US, param_file, tv, just_read_params)
!! only read parameters without changing h.
! Local variables
real, dimension(SZI_(G),SZJ_(G)) :: &
eta_sfc ! The free surface height that the model should use [m].
eta_sfc ! The free surface height that the model should use [Z ~> m].
real, dimension(SZI_(G),SZJ_(G),SZK_(G)+1) :: &
eta ! The free surface height that the model should use [m].
eta ! The free surface height that the model should use [Z ~> m].
real :: dilate ! A ratio by which layers are dilated [nondim].
real :: scale_factor ! A scaling factor for the eta_sfc values that are read
! in, which can be used to change units, for example.
Expand Down Expand Up @@ -1039,15 +1039,15 @@ subroutine depress_surface(h, G, GV, US, param_file, tv, just_read_params)
call log_param(param_file, mdl, "INPUTDIR/SURFACE_HEIGHT_IC_FILE", filename)

call get_param(param_file, mdl, "SURFACE_HEIGHT_IC_SCALE", scale_factor, &
"A scaling factor to convert SURFACE_HEIGHT_IC_VAR into "//&
"units of m", units="variable", default=1.0, do_not_log=just_read)
"A scaling factor to convert SURFACE_HEIGHT_IC_VAR into units of m", &
units="variable", default=1.0, scale=US%m_to_Z, do_not_log=just_read)

if (just_read) return ! All run-time parameters have been read, so return.

call MOM_read_data(filename, eta_srf_var, eta_sfc, G%Domain, scale=scale_factor)

! Convert thicknesses to interface heights.
call find_eta(h, tv, G, GV, US, eta, eta_to_m=1.0)
call find_eta(h, tv, G, GV, US, eta)

do j=js,je ; do i=is,ie ; if (G%mask2dT(i,j) > 0.0) then
! if (eta_sfc(i,j) < eta(i,j,nz+1)) then
Expand Down Expand Up @@ -1398,8 +1398,9 @@ subroutine initialize_velocity_circular(u, v, G, US, param_file, just_read_param
!! only read parameters without changing h.
! Local variables
character(len=200) :: mdl = "initialize_velocity_circular"
real :: circular_max_u
real :: dpi, psi1, psi2
real :: circular_max_u ! The amplitude of the zonal flow [L T-1 ~> m s-1]
real :: dpi ! A local variable storing pi = 3.14159265358979...
real :: psi1, psi2 ! Values of the streamfunction at two points [L2 T-1 ~> m2 s-1]
logical :: just_read ! If true, just read parameters but set nothing.
integer :: i, j, k, is, ie, js, je, Isq, Ieq, Jsq, Jeq, nz
is = G%isc ; ie = G%iec ; js = G%jsc ; je = G%jec ; nz = G%ke
Expand All @@ -1410,7 +1411,7 @@ subroutine initialize_velocity_circular(u, v, G, US, param_file, just_read_param
call get_param(param_file, mdl, "CIRCULAR_MAX_U", circular_max_u, &
"The amplitude of zonal flow from which to scale the "// &
"circular stream function [m s-1].", &
units="m s-1", default=0., scale=US%L_T_to_m_s, do_not_log=just_read)
units="m s-1", default=0., scale=US%m_s_to_L_T, do_not_log=just_read)

if (just_read) return ! All run-time parameters have been read, so return.

Expand All @@ -1419,29 +1420,29 @@ subroutine initialize_velocity_circular(u, v, G, US, param_file, just_read_param
do k=1,nz ; do j=js,je ; do I=Isq,Ieq
psi1 = my_psi(I,j)
psi2 = my_psi(I,j-1)
u(I,j,k) = (psi1-psi2) / (G%US%L_to_m*G%dy_Cu(I,j)) ! *(circular_max_u*G%len_lon/(2.0*dpi))
u(I,j,k) = (psi1 - psi2) / G%dy_Cu(I,j) ! *(circular_max_u*G%len_lon/(2.0*dpi))
enddo ; enddo ; enddo
do k=1,nz ; do J=Jsq,Jeq ; do i=is,ie
psi1 = my_psi(i,J)
psi2 = my_psi(i-1,J)
v(i,J,k) = (psi2-psi1) / (G%US%L_to_m*G%dx_Cv(i,J)) ! *(circular_max_u*G%len_lon/(2.0*dpi))
v(i,J,k) = (psi2 - psi1) / G%dx_Cv(i,J) ! *(circular_max_u*G%len_lon/(2.0*dpi))
enddo ; enddo ; enddo

contains

!> Returns the value of a circular stream function at (ig,jg)
!> Returns the value of a circular stream function at (ig,jg) in [L2 T-1 ~> m2 s-1]
real function my_psi(ig,jg)
integer :: ig !< Global i-index
integer :: jg !< Global j-index
! Local variables
real :: x, y, r
real :: x, y, r ! [nondim]

x = 2.0*(G%geoLonBu(ig,jg)-G%west_lon) / G%len_lon - 1.0 ! -1<x<1
y = 2.0*(G%geoLatBu(ig,jg)-G%south_lat) / G%len_lat - 1.0 ! -1<y<1
r = sqrt( x**2 + y**2 ) ! Circular stream function is a function of radius only
r = min(1.0, r) ! Flatten stream function in corners of box
my_psi = 0.5*(1.0 - cos(dpi*r))
my_psi = my_psi * (circular_max_u*G%len_lon*1e3 / dpi) ! len_lon is in km
my_psi = my_psi * (circular_max_u * G%US%m_to_L*G%len_lon*1e3 / dpi) ! len_lon is in km
end function my_psi

end subroutine initialize_velocity_circular
Expand Down Expand Up @@ -2019,8 +2020,8 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, G, GV, US, PF, just_read_param

! Local variables for ALE remapping
real, dimension(:), allocatable :: hTarget ! Target thicknesses [Z ~> m].
real, dimension(:,:), allocatable :: area_shelf_h
real, dimension(:,:), allocatable, target :: frac_shelf_h
real, dimension(:,:), allocatable :: area_shelf_h ! Shelf-covered area per grid cell [L2 ~> m2]
real, dimension(:,:), allocatable, target :: frac_shelf_h ! Fractional shelf area per grid cell [nondim]
real, dimension(:,:,:), allocatable, target :: tmpT1dIn, tmpS1dIn
real, dimension(:,:,:), allocatable :: tmp_mask_in
real, dimension(:,:,:), allocatable :: h1 ! Thicknesses [H ~> m or kg m-2].
Expand Down Expand Up @@ -2060,7 +2061,7 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, G, GV, US, PF, just_read_param

! call mpp_get_compute_domain(G%domain%mpp_domain,isc,iec,jsc,jec)

reentrant_x = .false. ; call get_param(PF, mdl, "REENTRANT_X", reentrant_x,default=.true.)
reentrant_x = .false. ; call get_param(PF, mdl, "REENTRANT_X", reentrant_x, default=.true.)
tripolar_n = .false. ; call get_param(PF, mdl, "TRIPOLAR_N", tripolar_n, default=.false.)
call get_param(PF, mdl, "MINIMUM_DEPTH", min_depth, default=0.0, scale=US%m_to_Z)

Expand Down Expand Up @@ -2204,14 +2205,14 @@ subroutine MOM_temp_salt_initialize_from_Z(h, tv, G, GV, US, PF, just_read_param
if (.not.file_exists(shelf_file, G%Domain)) call MOM_error(FATAL, &
"MOM_temp_salt_initialize_from_Z: Unable to open shelf file "//trim(shelf_file))

call MOM_read_data(shelf_file, trim(area_varname), area_shelf_h, G%Domain)
call MOM_read_data(shelf_file, trim(area_varname), area_shelf_h, G%Domain, scale=US%m_to_L**2)

! Initialize frac_shelf_h with zeros (open water everywhere)
frac_shelf_h(:,:) = 0.0
! Compute fractional ice shelf coverage of h
do j=jsd,jed ; do i=isd,ied
if (G%areaT(i,j) > 0.0) &
frac_shelf_h(i,j) = area_shelf_h(i,j) / (US%L_to_m**2*G%areaT(i,j))
frac_shelf_h(i,j) = area_shelf_h(i,j) / G%areaT(i,j)
enddo ; enddo
! Pass to the pointer for use as an argument to regridding_main
shelf_area => frac_shelf_h
Expand Down
2 changes: 1 addition & 1 deletion src/parameterizations/lateral/MOM_internal_tides.F90
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ subroutine propagate_int_tide(h, tv, cn, TKE_itidal_input, vel_btTide, Nb, dt, &
! Dissipate energy if Fr>1; done here with an arbitrary time scale
if (Fr2_max > 1.0) then
En_initial = sum(CS%En(i,j,:,fr,m)) ! for debugging
! Calculate effective decay rate [s-1] if breaking occurs over a time step
! Calculate effective decay rate [T-1 ~> s-1] if breaking occurs over a time step
loss_rate = (1.0 - Fr2_max) / (Fr2_max * dt)
do a=1,CS%nAngle
! Determine effective dissipation rate (Wm-2)
Expand Down
2 changes: 0 additions & 2 deletions src/parameterizations/lateral/MOM_thickness_diffuse.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1400,7 +1400,6 @@ subroutine add_detangling_Kh(h, e, Kh_u, Kh_v, KH_u_CFL, KH_v_CFL, tv, dt, G, GV
! normalized by the arithmetic mean thickness.
real :: Kh_scale ! A ratio by which Kh_u_CFL is scaled for maximally jagged
! layers [nondim].
! real :: Kh_det ! The detangling diffusivity [m2 s-1].
real :: h_neglect ! A thickness that is so small it is usually lost
! in roundoff and can be neglected [H ~> m or kg m-2].

Expand All @@ -1422,7 +1421,6 @@ subroutine add_detangling_Kh(h, e, Kh_u, Kh_v, KH_u_CFL, KH_v_CFL, tv, dt, G, GV
! the damping timescale [T-1 ~> s-1].
real :: Fn_R ! A function of Rsl, such that Rsl < Fn_R < 1.
real :: denom, I_denom ! A denominator and its inverse, various units.
! real :: Kh_min ! A local floor on the diffusivity [m2 s-1].
real :: Kh_max ! A local ceiling on the diffusivity [L2 T-1 ~> m2 s-1].
real :: wt1, wt2 ! Nondimensional weights.
! Variables used only in testing code.
Expand Down
2 changes: 1 addition & 1 deletion src/parameterizations/vertical/MOM_diapyc_energy_req.F90
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ subroutine find_PE_chg_orig(Kddt_h, h_k, b_den_1, dTe_term, dSe_term, &
real :: b1Kd ! Temporary array [nondim]
real :: ColHt_chg ! The change in column thickness [Z ~> m].
real :: dColHt_max ! The change in column thickness for infinite diffusivity [Z ~> m].
real :: dColHt_dKd ! The partial derivative of column thickness with diffusivity [s Z-1 ~> s m-1].
real :: dColHt_dKd ! The partial derivative of column thickness with Kddt_h [Z H-1 ~> 1 or m3 kg-1].
real :: dT_k, dT_km1 ! Temporary arrays [degC].
real :: dS_k, dS_km1 ! Temporary arrays [ppt].
real :: I_Kr_denom ! Temporary arrays [H-2 ~> m-2 or m4 kg-2].
Expand Down
Loading

0 comments on commit 02f257b

Please sign in to comment.