Changeset 5821


Ignore:
Timestamp:
Sep 18, 2025, 10:29:26 AM (2 months ago)
Author:
idelkadi
Message:

Added a formulation to prescribe effective cloud size as a hyperbolic tangent function of pressure for calculating radiative fluxes related to 3D cloud effects.
Activation is controlled in namelist_ecrad by the logical key ok_separation_tanh

Location:
LMDZ6/trunk/libf/phylmd/ecrad
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • LMDZ6/trunk/libf/phylmd/ecrad/lmdz/radiation_scheme_mod.f90

    r5675 r5821  
    428428               &  driver_config%high_inv_effective_size, 0.8_jprb, 0.45_jprb, &
    429429               &  KIDIA, KFDIA)
    430    else if (driver_config%ok_separation) then
     430   else if (driver_config%ok_separation_eta) then
    431431     call cloud%param_cloud_effective_separation_eta(klon, klev, &
     432               &  thermodynamics%pressure_hl, &
     433               &  driver_config%cloud_separation_scale_surface, &
     434               &  driver_config%cloud_separation_scale_toa, &
     435               &  driver_config%cloud_separation_scale_power, &
     436               &  driver_config%cloud_inhom_separation_factor, &
     437               &  KIDIA, KFDIA)
     438   else if (driver_config%ok_separation_tanh) then
     439     call cloud%param_cloud_effective_separation_tanh(klon, klev, &
    432440               &  thermodynamics%pressure_hl, &
    433441               &  driver_config%cloud_separation_scale_surface, &
     
    11341142               &  driver_config%high_inv_effective_size, 0.8_jprb, 0.45_jprb, &
    11351143               &  KIDIA, KFDIA)
    1136    else if (driver_config%ok_separation) then
     1144   else if (driver_config%ok_separation_eta) then
    11371145     call cloud%param_cloud_effective_separation_eta(klon, klev, &
     1146               &  thermodynamics%pressure_hl, &
     1147               &  driver_config%cloud_separation_scale_surface, &
     1148               &  driver_config%cloud_separation_scale_toa, &
     1149               &  driver_config%cloud_separation_scale_power, &
     1150               &  driver_config%cloud_inhom_separation_factor, &
     1151               &  KIDIA, KFDIA)
     1152   else if (driver_config%ok_separation_tanh) then
     1153     call cloud%param_cloud_effective_separation_tanh(klon, klev, &
    11381154               &  thermodynamics%pressure_hl, &
    11391155               &  driver_config%cloud_separation_scale_surface, &
  • LMDZ6/trunk/libf/phylmd/ecrad/lmdz/setup_config_from_lmdz.f90

    r5675 r5821  
    99  type driver_config_type
    1010     logical    :: ok_effective_size  = .true.
    11      logical    :: ok_separation = .false.   
     11     logical    :: ok_separation_eta = .false.   
     12     logical    :: ok_separation_tanh = .false.
    1213     real(jprb) :: high_inv_effective_size   = -1.0_jprb ! m-1
    1314     real(jprb) :: middle_inv_effective_size = -1.0_jprb ! m-1
     
    4445    character(*), intent(in)          :: file_name
    4546    logical, intent(out), optional    :: is_success
    46     logical    :: ok_effective_size, ok_separation
     47    logical    :: ok_effective_size, ok_separation_eta, ok_separation_tanh
    4748    integer    :: iosopen ! Status after calling open
    4849    real(jprb) :: high_inv_effective_size
     
    6162    logical :: do_save_inputs
    6263
    63     namelist /radiation_driver/ ok_effective_size, ok_separation, &
     64    namelist /radiation_driver/ ok_effective_size, ok_separation_eta, ok_separation_tanh, &
    6465         &  frac_std, overlap_decorr_length, kdecolat, &
    6566         &  low_decorrelation_length, mid_decorrelation_length, high_decorrelation_length, &
     
    7071
    7172    ok_effective_size = .false.
    72     ok_separation = .false.
     73    ok_separation_eta = .false.
     74    ok_separation_tanh = .false.
    7375    high_inv_effective_size   = -1.0_jprb
    7476    middle_inv_effective_size = -1.0_jprb
     
    109111    ! Copy namelist data into configuration object
    110112    this%ok_effective_size = ok_effective_size
    111     this%ok_separation = ok_separation
     113    this%ok_separation_eta = ok_separation_eta
     114    this%ok_separation_tanh = ok_separation_tanh
    112115    this%frac_std = frac_std
    113116    this%overlap_decorr_length = overlap_decorr_length
  • LMDZ6/trunk/libf/phylmd/ecrad/radiation/radiation_cloud.F90

    r5690 r5821  
    9191    procedure :: create_inv_cloud_effective_size_eta
    9292    procedure :: param_cloud_effective_separation_eta
     93    procedure :: param_cloud_effective_separation_tanh
    9394    procedure :: crop_cloud_fraction
    9495    procedure :: out_of_physical_bounds
     
    774775  end subroutine param_cloud_effective_separation_eta
    775776
    776 
     777  !AI 20 mai 2025
     778 !Nouvelle param Lx=f(P) avec Lf(P) tgte hyperb
     779 subroutine param_cloud_effective_separation_tanh(this, ncol, nlev, &
     780     &  pressure_hl, &
     781     &  lx_surf, lx_toa, gama, &
     782     &  inhom_separation_factor, istartcol, iendcol)
     783
     784  use yomhook,                  only : lhook, dr_hook, jphook
     785  use write_field_phy
     786  implicit none
     787
     788  class(cloud_type), intent(inout) :: this
     789  integer,           intent(in)    :: ncol, nlev
     790  ! Pressure on half levels (Pa) : size should be (ncol, nlev+1)
     791  real(jprb),        intent(in)    :: pressure_hl(:,:)
     792  ! Separation distances at surface and top-of-atmosphere (m)
     793  real(jprb),        intent(in)    :: lx_surf, lx_toa
     794  ! Facteur de raideur
     795  real(jprb),        intent(in)    :: gama
     796  ! Optional factor
     797  real(jprb), optional, intent(in) :: inhom_separation_factor
     798  integer,    optional, intent(in) :: istartcol, iendcol
     799
     800  ! Parameters (AI attention a revoir)
     801  real(kind=jprb), parameter :: eps = 1.0e-5_jprb
     802
     803  ! Locals
     804  real(jprb) :: eff_separation(ncol,nlev)
     805  real(jprb) :: Lmin, Lmax, Pmin, Pmax, p_mean, p0, inhom_sep_factor, alpha
     806  integer :: jcol, k
     807  integer :: i1, i2
     808  real(jphook) :: hook_handle
     809  real(jprb) :: frac, denom1, denom2
     810  real(jprb) :: pdiff
     811
     812  ! Hook entry
     813  if (lhook) call dr_hook('radiation_cloud:param_cloud_effective_separation_eta',0,hook_handle)
     814
     815  ! inhom separation factor default
     816  if (present(inhom_separation_factor)) then
     817    inhom_sep_factor = inhom_separation_factor
     818  else
     819    inhom_sep_factor = 1.0_jprb
     820  end if
     821
     822  ! (re)allocation of output arrays
     823  if (allocated(this%inv_cloud_effective_size)) then
     824    deallocate(this%inv_cloud_effective_size)
     825  end if
     826  if (allocated(this%inv_inhom_effective_size)) then
     827    deallocate(this%inv_inhom_effective_size)
     828  end if
     829
     830  allocate(this%inv_cloud_effective_size(ncol, nlev))
     831  allocate(this%inv_inhom_effective_size(ncol, nlev))
     832
     833  ! columns range
     834  if (present(istartcol)) then
     835    i1 = istartcol
     836  else
     837    i1 = 1
     838  end if
     839
     840  if (present(iendcol)) then
     841    i2 = iendcol
     842  else
     843    i2 = ncol
     844  end if
     845
     846  ! map inputs to local names
     847  Lmin = lx_surf
     848  Lmax = lx_toa
     849
     850  ! Determine pressure range (expect pressure_hl(:,1) ~ surface, (:,nlev+1) ~ TOA)
     851  ! Use safe guards if pressure_hl dimension is smaller/wrong => runtime will fail earlier
     852  Pmin = minval(pressure_hl(:,nlev+1))
     853  Pmax = maxval(pressure_hl(:,1))
     854
     855  ! compute centre and alpha (guard if Pmax==Pmin)
     856  p0 = 0.5_jprb*(Pmax + Pmin)
     857  pdiff = (Pmax - Pmin)
     858  if (abs(pdiff) < eps) then
     859    ! improbable but guard against division by zero
     860    alpha = gama / eps
     861    write(*,*) 'Warning: Pmax - Pmin trop petit -> alpha forcé'
     862  else
     863    alpha = gama / pdiff
     864  end if
     865
     866  ! Main loops
     867  do jcol = i1, i2
     868    do k = 1, nlev
     869      ! pression moyenne de la couche k (half-levels k and k+1 must exist)
     870      p_mean = 0.5_jprb * (pressure_hl(jcol,k) + pressure_hl(jcol,k+1))
     871
     872      ! loi hyperbolique bornée entre Lmin et Lmax
     873      eff_separation(jcol,k) = 0.5_jprb*(Lmax + Lmin) - 0.5_jprb*(Lmax - Lmin) * tanh(alpha*(p_mean - p0))
     874
     875      ! borne de sécurité (eviter 0 ou négatif)
     876      eff_separation(jcol,k) = max(eps, eff_separation(jcol,k))
     877
     878      ! fraction safe clamp
     879      frac = this%fraction(jcol,k)
     880      if (frac < 0.0_jprb) then
     881        frac = 0.0_jprb
     882      else if (frac > 1.0_jprb) then
     883        frac = 1.0_jprb
     884      end if
     885
     886      ! denominators and protection
     887      denom1 = eff_separation(jcol,k) * sqrt( max(eps, frac*(1.0_jprb - frac)) )
     888      if (denom1 < eps) denom1 = eps
     889      this%inv_cloud_effective_size(jcol,k) = 1.0_jprb / denom1
     890
     891      denom2 = eff_separation(jcol,k) * inhom_sep_factor * sqrt( max(eps, 0.5_jprb*frac*(1.0_jprb - 0.5_jprb*frac)) )
     892      if (denom2 < eps) denom2 = eps
     893      this%inv_inhom_effective_size(jcol,k) = 1.0_jprb / denom2
     894
     895    end do
     896  end do
     897
     898  ! diagnostics
     899  !CALL writefield_phy('pressure_hl',pressure_hl,nlev+1)
     900  !CALL writefield_phy('eff_lx',eff_separation,nlev)
     901
     902  if (lhook) call dr_hook('radiation_cloud:param_cloud_effective_separation_eta',1,hook_handle)
     903
     904 end subroutine param_cloud_effective_separation_tanh
     905 
    777906  !---------------------------------------------------------------------
    778907  ! Remove "ghost" clouds: those with a cloud fraction that is too
Note: See TracChangeset for help on using the changeset viewer.