diff --git a/makefile b/makefile index e36063b21f51e4d3a8e88e96593d4e2bc051e039..a9f87d3ba74a6fa4714d422ca0af62d903a53483 100644 --- a/makefile +++ b/makefile @@ -10,7 +10,7 @@ ifeq ($(COMPILER),gnu) FC = gfortran endif -OBJ_F90 = sfx_phys_const.o sfx_common.o sfx_config.o sfx_io.o sfx_data.o sfx_surface.o sfx_log_param.o sfx_log.o sfx_most_param.o sfx_most.o sfx_most_snow_param.o sfx_most_snow.o sfx_sheba_param.o sfx_sheba.o sfx_esm_param.o sfx_esm.o sfx_run.o sfx_main.o +OBJ_F90 = sfx_phys_const.o sfx_common.o sfx_io.o sfx_data.o sfx_z0m_all_surface.o sfx_surface.o sfx_config.o sfx_log_param.o sfx_log.o sfx_most_param.o sfx_most.o sfx_most_snow_param.o sfx_most_snow.o sfx_sheba_param.o sfx_sheba.o sfx_esm_param.o sfx_esm.o sfx_run.o sfx_main.o OBJ_F = OBJ = $(OBJ_F90) $(OBJ_F) diff --git a/srcF/sfx_most_snow.f90 b/srcF/sfx_most_snow.f90 index 9b022d15391c318540b722c49fa46358359caf95..008fd65742551386c28fe5134941f030d661b55d 100644 --- a/srcF/sfx_most_snow.f90 +++ b/srcF/sfx_most_snow.f90 @@ -24,6 +24,7 @@ module sfx_most_snow public :: get_surface_fluxes public :: get_surface_fluxes_vec public :: get_psi + integer z0m_id ! -------------------------------------------------------------------------------- ! -------------------------------------------------------------------------------- @@ -91,6 +92,7 @@ contains real :: Tsemi !< semi-sum of potential temperature at 'h' and at surface [K] real :: dQ !< difference between humidity at 'h' and at surface [g/g] real :: z0_m !< surface aerodynamic roughness (should be < 0 for water bodies surface) + real :: z0_map !< surface aerodynamic roughness (should be < 0 for water bodies surface) ! ---------------------------------------------------------------------------- ! --- local variables @@ -121,7 +123,7 @@ contains real S_mean, Lsnow real z0_s, h_salt - + integer surface_type !< surface type = (ocean || land) @@ -153,8 +155,14 @@ contains dT = meteo%dT dQ = meteo%dQ h = meteo%h - z0_m = meteo%z0_m + !z0_m = meteo%z0_m + z0_map = meteo%z0_m + + call get_dynamic_roughness_definition(surface_type, ocean_z0m_id, land_z0m_id, lake_z0m_id, snow_z0m_id, & + forest_z0m_id, usersf_z0m_id, z0m_id) + + call get_dynamic_roughness_all(z0_m, u_dyn0, U, depth, h, numerics%maxiters_charnock, z0_map, z0m_id) ! --- define surface type if (z0_m < 0.0) then surface_type = surface_ocean diff --git a/srcF/sfx_surface.f90 b/srcF/sfx_surface.f90 index 55329333be8a4326b204448185dcace6f9bbf329..a7c9b37d21db7d002fdc2222a3e663cfa68817d3 100644 --- a/srcF/sfx_surface.f90 +++ b/srcF/sfx_surface.f90 @@ -6,6 +6,7 @@ module sfx_surface ! modules used ! -------------------------------------------------------------------------------- use sfx_phys_const + use sfx_z0m_all_surface ! -------------------------------------------------------------------------------- ! directives list @@ -20,6 +21,8 @@ module sfx_surface #endif public :: get_charnock_roughness public :: get_thermal_roughness + public :: get_dynamic_roughness_all + public :: get_dynamic_roughness_definition ! -------------------------------------------------------------------------------- @@ -28,12 +31,39 @@ module sfx_surface integer, public, parameter :: surface_land = 1 !< land surface integer, public, parameter :: surface_lake = 2 !< lake surface integer, public, parameter :: surface_snow = 3 !< snow covered surface + integer, public, parameter :: surface_forest = 4 !< snow covered surface + integer, public, parameter :: surface_user = 5 !< snow covered surface character(len = 16), parameter :: surface_ocean_tag = 'ocean' character(len = 16), parameter :: surface_land_tag = 'land' character(len = 16), parameter :: surface_lake_tag = 'lake' character(len = 16), parameter :: surface_snow_tag = 'snow' + character(len = 16), parameter :: surface_forest_tag = 'forest' + character(len = 16), parameter :: surface_user_tag = 'user' + + integer, public, parameter :: z0m_ch = 0 + integer, public, parameter :: z0m_fe = 1 + integer, public, parameter :: z0m_ow = 2 + integer, public, parameter :: z0m_map = 3 + integer, public, parameter :: z0m_user = 4 + + + character(len = 16), parameter :: z0m_tag_ch = 'charnock' + character(len = 16), parameter :: z0m_tag_fe = 'fetch' + character(len = 16), parameter :: z0m_tag_ow = 'owen' + character(len = 16), parameter :: z0m_tag_map = 'map' + character(len = 16), parameter :: z0m_tag_user = 'user' + + + integer, public, parameter :: ocean_z0m_id = z0m_ch !< ocean surface + integer, public, parameter :: land_z0m_id = z0m_map !< land surface + integer, public, parameter :: lake_z0m_id = z0m_fe !< lake surface + integer, public, parameter :: snow_z0m_id = z0m_ow !< snow covered surface + integer, public, parameter :: forest_z0m_id = z0m_map !< forest csurface + integer, public, parameter :: usersf_z0m_id = z0m_map !< user surface + + real, public, parameter :: depth = 1.0 ! -------------------------------------------------------------------------------- real, parameter, private :: kappa = 0.40 !< von Karman constant [n/d] ! -------------------------------------------------------------------------------- @@ -42,12 +72,12 @@ module sfx_surface !< z0 = Re_visc_min * (nu / u_dyn) + gamma_c * (u_dyn^2 / g) ! -------------------------------------------------------------------------------- - real, parameter :: gamma_c = 0.0144 - real, parameter :: Re_visc_min = 0.111 + !real, parameter :: gamma_c = 0.0144 + !real, parameter :: Re_visc_min = 0.111 - real, parameter :: h_charnock = 10.0 - real, parameter :: c1_charnock = log(h_charnock * (g / gamma_c)) - real, parameter :: c2_charnock = Re_visc_min * nu_air * (g / gamma_c) + !real, parameter :: h_charnock = 10.0 + !real, parameter :: c1_charnock = log(h_charnock * (g / gamma_c)) + !real, parameter :: c2_charnock = Re_visc_min * nu_air * (g / gamma_c) ! -------------------------------------------------------------------------------- !< Re fully roughness minimum value [n/d] @@ -85,6 +115,10 @@ contains id = surface_lake else if (trim(tag) == trim(surface_snow_tag)) then id = surface_snow + else if (trim(tag) == trim(surface_forest_tag)) then + id = surface_forest + else if (trim(tag) == trim(surface_user_tag)) then + id = surface_user end if end function @@ -103,10 +137,55 @@ contains tag = surface_lake_tag else if (id == surface_snow) then tag = surface_snow_tag + else if (id == surface_forest) then + tag = surface_forest_tag + else if (id == surface_user) then + tag = surface_user_tag end if end function + + function get_surface_z0m_id(tag_z0m) result(z0m_id) + implicit none + character(len=*), intent(in) :: tag_z0m + integer :: z0m_id + + z0m_id = - 1 + if (trim(tag_z0m) == trim(z0m_tag_ch)) then + z0m_id = z0m_ch + else if (trim(tag_z0m) == trim(z0m_tag_fe)) then + z0m_id = z0m_fe + else if (trim(tag_z0m) == trim(z0m_tag_ow)) then + z0m_id = z0m_ow + else if (trim(tag_z0m) == trim(z0m_tag_map)) then + z0m_id = z0m_map + else if (trim(tag_z0m) == trim(z0m_tag_user)) then + z0m_id = z0m_user + end if + + end function + + function get_surface_z0m_tag(z0m_id) result(tag_z0m) + implicit none + integer :: z0m_id + character(len=:), allocatable :: tag_z0m + + tag_z0m = 'undefined' + if (z0m_id == z0m_ch) then + tag_z0m = z0m_tag_ch + else if (z0m_id == z0m_fe) then + tag_z0m = z0m_tag_fe + else if (z0m_id == z0m_ow) then + tag_z0m = z0m_tag_ow + else if (z0m_id == z0m_map) then + tag_z0m = z0m_tag_map + else if (z0m_id == z0m_user) then + tag_z0m = z0m_tag_user + end if + end function + + #if defined(INCLUDE_CXX) subroutine set_c_struct_sfx_surface_param_values(surface_param) use sfx_data @@ -133,9 +212,77 @@ contains end subroutine set_c_struct_sfx_surface_param_values #endif - ! charnock roughness definition + ! dynamic roughness definition ! -------------------------------------------------------------------------------- - subroutine get_charnock_roughness(z0_m, u_dyn0, U, h, maxiters) + subroutine get_dynamic_roughness_definition(surface_type, ocean_z0m_id, land_z0m_id, lake_z0m_id, snow_z0m_id, & + forest_z0m_id, usersf_z0m_id, z0m_id) + ! ---------------------------------------------------------------------------- + integer, intent(out) :: z0m_id + + integer, intent(in) :: surface_type + + integer, intent(in) :: ocean_z0m_id + integer, intent(in) :: land_z0m_id + integer, intent(in) :: lake_z0m_id + integer, intent(in) :: snow_z0m_id + integer, intent(in) :: forest_z0m_id + integer, intent(in) :: usersf_z0m_id + + ! --------------------------------------------------------------------------- + + if (surface_type == surface_ocean) then + z0m_id = ocean_z0m_id + else if (surface_type == surface_land) then + z0m_id = land_z0m_id + else if (surface_type == surface_snow) then + z0m_id = snow_z0m_id + else if (surface_type == surface_lake) then + z0m_id = lake_z0m_id + else if (surface_type == surface_forest) then + z0m_id = forest_z0m_id + else if (surface_type == surface_user) then + z0m_id = usersf_z0m_id + end if + + end subroutine + + ! ---------------------------------------------------------------------------- + subroutine get_dynamic_roughness_all(z0_m, u_dyn0, U, depth, h,& + maxiters, z0m_map, z0m_id) +! ---------------------------------------------------------------------------- + real, intent(out) :: z0_m !< aerodynamic roughness [m] + real, intent(out) :: u_dyn0 !< dynamic velocity in neutral conditions [m/s] + + real, intent(in) :: U !< abs(wind speed) [m/s] + real, intent(in) :: depth !< depth [m] + real, intent(in) :: h !< constant flux layer height [m] + real, intent(in) :: z0m_map !< aerodynamic roughness from map [m] + integer, intent(in) :: maxiters !< maximum number of iterations + + integer, intent(in) :: z0m_id +! --------------------------------------------------------------------------- + + + if (z0m_id == z0m_ch) then + call get_dynamic_roughness_ch(z0_m, u_dyn0, U, h, maxiters) + else if (z0m_id == z0m_fe) then + call get_dynamic_roughness_fetch(z0_m, u_dyn0, U, depth, h, maxiters) + else if (z0m_id == z0m_ow) then + call get_dynamic_roughness_ow(z0_m, u_dyn0, U, h, maxiters) + else if (z0m_id == z0m_map) then + call get_dynamic_roughness_map(z0_m, u_dyn0, U, h, z0m_map) + else if (z0m_id == z0m_user) then + write(*, *) 'z0m_user' +end if + +end subroutine +! -------------------------------------------------------------------------------- + + + + + + subroutine get_charnock_roughness(z0_m, u_dyn0, U, h, maxiters) ! ---------------------------------------------------------------------------- real, intent(out) :: z0_m !< aerodynamic roughness [m] real, intent(out) :: u_dyn0 !< dynamic velocity in neutral conditions [m/s] diff --git a/srcF/sfx_z0m_all.f90 b/srcF/sfx_z0m_all.f90 index c325e4d427b0e5d9b059731750bdd33c083e82bd..2dac487bc5de3f639948cf6b1d364f801593a5a0 100644 --- a/srcF/sfx_z0m_all.f90 +++ b/srcF/sfx_z0m_all.f90 @@ -168,16 +168,10 @@ module sfx_z0m_all ! ---------------------------------------------------------------------------- subroutine get_dynamic_roughness_definition(surface_type, id_ocean, id_land, id_snow, id_lake, & - id_forest, id_user, ocean_z0m_id, land_z0m_id, lake_z0m_id, snow_z0m_id, & - forest_z0m_id, usersf_z0m_id) + id_forest, id_user, z0m_id) ! ---------------------------------------------------------------------------- - real, intent(out) :: ocean_z0m_id - real, intent(out) :: land_z0m_id - real, intent(out) :: lake_z0m_id - real, intent(out) :: snow_z0m_id - real, intent(out) :: forest_z0m_id - real, intent(out) :: usersf_z0m_id - + real, intent(out) :: z0m_id + real, intent(in) :: surface_type real, intent(in) :: id_ocean @@ -190,17 +184,17 @@ module sfx_z0m_all ! --------------------------------------------------------------------------- if (surface_type == surface_ocean) then - ocean_z0m_id = id_ocean + z0m_id = id_ocean else if (surface_type == surface_land) then - land_z0m_id = id_land + z0m_id = id_land else if (surface_type == surface_snow) then - snow_z0m_id = id_snow + z0m_id = id_snow else if (surface_type == surface_lake) then - lake_z0m_id = id_lake + z0m_id = id_lake else if (surface_type == surface_forest) then - forest_z0m_id = id_forest + z0m_id = id_forest else if (surface_type == surface_user) then - usersf_z0m_id = id_user + z0m_id = id_user end if end subroutine