LCOV - code coverage report
Current view: top level - physics/rrtmgp/ext/rte-frontend - mo_source_functions.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 39 100 39.0 %
Date: 2024-12-17 22:39:59 Functions: 6 17 35.3 %

          Line data    Source code
       1             : ! This code is part of Radiative Transfer for Energetics (RTE)
       2             : !
       3             : ! Contacts: Robert Pincus and Eli Mlawer
       4             : ! email:  rrtmgp@aer.com
       5             : !
       6             : ! Copyright 2015-  Atmospheric and Environmental Research,
       7             : !    Regents of the University of Colorado,
       8             : !    Trustees of Columbia University in the City of New York
       9             : ! All right reserved.
      10             : !
      11             : ! Use and duplication is permitted under the terms of the
      12             : !    BSD 3-clause license, see http://opensource.org/licenses/BSD-3-Clause
      13             : ! -------------------------------------------------------------------------------------------------
      14             : !
      15             : !> Encapsulate source function arrays for longwave/lw/internal sources
      16             : !    and shortwave/sw/external source.
      17             : !
      18             : ! -------------------------------------------------------------------------------------------------
      19             : module mo_source_functions
      20             :   use mo_rte_kind,      only: wp
      21             :   use mo_optical_props, only: ty_optical_props
      22             :   implicit none
      23             :   private
      24             :   ! -------------------------------------------------------------------------------------------------
      25             :   !
      26             :   !> Type representing Planck source functions in \(W/m^2\)
      27             :   !>   computed at layer center, at layer edges using
      28             :   !>   spectral mapping in each direction separately, and at the surface
      29             :   !>
      30             :   type, extends(ty_optical_props), public :: ty_source_func_lw
      31             :     real(wp), allocatable, dimension(:,:,:) :: lay_source
      32             :         !! Planck source at layer average temperature (ncol, nlay, ngpt)
      33             :     real(wp), allocatable, dimension(:,:,:) :: lev_source_inc
      34             :         !! Planck source at layer edge in increasing ilay direction (ncol, nlay+1, ngpt)
      35             :     real(wp), allocatable, dimension(:,:,:) :: lev_source_dec
      36             :         !! Planck source at layer edge in decreasing ilay direction (ncol, nlay+1, ngpt)
      37             :     real(wp), allocatable, dimension(:,:  ) :: sfc_source
      38             :         !! Planck function at surface temperature
      39             :     real(wp), allocatable, dimension(:,:  ) :: sfc_source_Jac
      40             :         !! surface source Jacobian
      41             :   contains
      42             :     generic,   public :: alloc => alloc_lw, copy_and_alloc_lw
      43             :     procedure, private:: alloc_lw
      44             :     procedure, private:: copy_and_alloc_lw
      45             :     procedure, public :: is_allocated => is_allocated_lw
      46             :     procedure, public :: finalize     => finalize_lw
      47             :     procedure, public :: get_subset   => get_subset_range_lw
      48             :     procedure, public :: get_ncol     => get_ncol_lw
      49             :     procedure, public :: get_nlay     => get_nlay_lw
      50             :     ! validate?
      51             :   end type ty_source_func_lw
      52             :   ! -------------------------------------------------------------------------------------------------
      53             :   !
      54             :   ! Type for shortave sources: top-of-domain spectrally-resolved flux
      55             :   !   The type isn't used at this time, so it's declared as private.
      56             :   !
      57             :   type, extends(ty_optical_props), private :: ty_source_func_sw
      58             :     real(wp), allocatable, dimension(:,:  ) :: toa_source
      59             :   contains
      60             :     generic,   public :: alloc => alloc_sw, copy_and_alloc_sw
      61             :     procedure, private:: alloc_sw
      62             :     procedure, private:: copy_and_alloc_sw
      63             :     procedure, public :: is_allocated => is_allocated_sw
      64             :     procedure, public :: finalize => finalize_sw
      65             :     procedure, public :: get_subset => get_subset_range_sw
      66             :     procedure, public :: get_ncol => get_ncol_sw
      67             :     ! validate?
      68             :   end type ty_source_func_sw
      69             :   ! -------------------------------------------------------------------------------------------------
      70             : contains
      71             :   ! ------------------------------------------------------------------------------------------
      72             :   !
      73             :   !  Routines for initialization, validity checking, finalization
      74             :   !
      75             :   ! ------------------------------------------------------------------------------------------
      76             :   !
      77             :   ! Longwave
      78             :   !
      79             :   ! ------------------------------------------------------------------------------------------
      80     4476816 :   pure function is_allocated_lw(this)
      81             :     class(ty_source_func_lw), intent(in) :: this
      82             :     logical                              :: is_allocated_lw
      83             : 
      84             :     is_allocated_lw = this%is_initialized() .and. &
      85     4476816 :                       allocated(this%sfc_source)
      86     4476816 :   end function is_allocated_lw
      87             :   ! --------------------------------------------------------------
      88      746136 :   function alloc_lw(this, ncol, nlay) result(err_message)
      89             :     class(ty_source_func_lw),    intent(inout) :: this
      90             :     integer,                     intent(in   ) :: ncol, nlay
      91             :     character(len = 128)                       :: err_message
      92             : 
      93             :     integer :: ngpt
      94             : 
      95      746136 :     err_message = ""
      96      746136 :     if(.not. this%is_initialized()) &
      97           0 :       err_message = "source_func_lw%alloc: not initialized so can't allocate"
      98     2238408 :     if(any([ncol, nlay] <= 0)) &
      99           0 :       err_message = "source_func_lw%alloc: must provide positive extents for ncol, nlay"
     100      746136 :     if (err_message /= "") return
     101             : 
     102      746136 :     if(allocated(this%sfc_source))     deallocate(this%sfc_source)
     103      746136 :     if(allocated(this%sfc_source_Jac)) deallocate(this%sfc_source_Jac)
     104      746136 :     if(allocated(this%lay_source))     deallocate(this%lay_source)
     105      746136 :     if(allocated(this%lev_source_inc)) deallocate(this%lev_source_inc)
     106      746136 :     if(allocated(this%lev_source_dec)) deallocate(this%lev_source_dec)
     107             : 
     108      746136 :     ngpt = this%get_ngpt()
     109           0 :     allocate(this%sfc_source    (ncol,     ngpt), this%lay_source    (ncol,nlay,ngpt), &
     110    10445904 :              this%lev_source_inc(ncol,nlay,ngpt), this%lev_source_dec(ncol,nlay,ngpt))
     111     2238408 :     allocate(this%sfc_source_Jac(ncol,     ngpt))
     112             :   end function alloc_lw
     113             :   ! --------------------------------------------------------------
     114      746136 :   function copy_and_alloc_lw(this, ncol, nlay, spectral_desc) result(err_message)
     115             :     class(ty_source_func_lw),    intent(inout) :: this
     116             :     integer,                     intent(in   ) :: ncol, nlay
     117             :     class(ty_optical_props ),    intent(in   ) :: spectral_desc
     118             :     character(len = 128)                       :: err_message
     119             : 
     120      746136 :     err_message = ""
     121      746136 :     if(.not. spectral_desc%is_initialized()) then
     122           0 :       err_message = "source_func_lw%alloc: spectral_desc not initialized"
     123           0 :       return
     124             :     end if
     125      746136 :     call this%finalize()
     126      746136 :     err_message = this%init(spectral_desc)
     127      746136 :     if (err_message /= "") return
     128      746136 :     err_message = this%alloc(ncol,nlay)
     129             :   end function copy_and_alloc_lw
     130             :   ! ------------------------------------------------------------------------------------------
     131             :   !
     132             :   ! Shortwave
     133             :   !
     134             :   ! ------------------------------------------------------------------------------------------
     135           0 :   pure function is_allocated_sw(this)
     136             :     class(ty_source_func_sw), intent(in) :: this
     137             :     logical                              :: is_allocated_sw
     138             : 
     139             :     is_allocated_sw = this%ty_optical_props%is_initialized() .and. &
     140           0 :                       allocated(this%toa_source)
     141           0 :   end function is_allocated_sw
     142             :   ! --------------------------------------------------------------
     143           0 :   function alloc_sw(this, ncol) result(err_message)
     144             :     class(ty_source_func_sw),    intent(inout) :: this
     145             :     integer,                     intent(in   ) :: ncol
     146             :     character(len = 128)                       :: err_message
     147             : 
     148           0 :     err_message = ""
     149           0 :     if(.not. this%is_initialized()) &
     150           0 :       err_message = "source_func_sw%alloc: not initialized so can't allocate"
     151           0 :     if(ncol <= 0) &
     152           0 :       err_message = "source_func_sw%alloc: must provide positive extents for ncol"
     153           0 :     if (err_message /= "") return
     154             : 
     155           0 :     if(allocated(this%toa_source)) deallocate(this%toa_source)
     156             : 
     157           0 :     allocate(this%toa_source(ncol, this%get_ngpt()))
     158             :   end function alloc_sw
     159             :   ! --------------------------------------------------------------
     160           0 :   function copy_and_alloc_sw(this, ncol, spectral_desc) result(err_message)
     161             :     class(ty_source_func_sw),    intent(inout) :: this
     162             :     integer,                     intent(in   ) :: ncol
     163             :     class(ty_optical_props ),    intent(in   ) :: spectral_desc
     164             :     character(len = 128)                       :: err_message
     165             : 
     166           0 :     err_message = ""
     167           0 :     if(.not. spectral_desc%is_initialized()) then
     168           0 :       err_message = "source_func_sw%alloc: spectral_desc not initialized"
     169           0 :       return
     170             :     end if
     171           0 :     err_message = this%init(spectral_desc)
     172           0 :     if(err_message /= "") return
     173           0 :     err_message = this%alloc(ncol)
     174             :   end function copy_and_alloc_sw
     175             :   ! ------------------------------------------------------------------------------------------
     176             :   !
     177             :   ! Finalization (memory deallocation)
     178             :   !
     179             :   ! ------------------------------------------------------------------------------------------
     180     2238408 :   subroutine finalize_lw(this)
     181             :     class(ty_source_func_lw),    intent(inout) :: this
     182             : 
     183     2238408 :     if(allocated(this%lay_source    )) deallocate(this%lay_source)
     184     2238408 :     if(allocated(this%lev_source_inc)) deallocate(this%lev_source_inc)
     185     2238408 :     if(allocated(this%lev_source_dec)) deallocate(this%lev_source_dec)
     186     2238408 :     if(allocated(this%sfc_source    )) deallocate(this%sfc_source)
     187     2238408 :     if(allocated(this%sfc_source_Jac)) deallocate(this%sfc_source_Jac)
     188     2238408 :     call this%ty_optical_props%finalize()
     189     2238408 :   end subroutine finalize_lw
     190             :   ! --------------------------------------------------------------
     191           0 :   subroutine finalize_sw(this)
     192             :     class(ty_source_func_sw),    intent(inout) :: this
     193             : 
     194           0 :     if(allocated(this%toa_source    )) deallocate(this%toa_source)
     195           0 :     call this%ty_optical_props%finalize()
     196           0 :   end subroutine finalize_sw
     197             :   ! ------------------------------------------------------------------------------------------
     198             :   !
     199             :   !  Routines for finding the problem size
     200             :   !
     201             :   ! ------------------------------------------------------------------------------------------
     202     2238408 :   pure function get_ncol_lw(this)
     203             :     class(ty_source_func_lw), intent(in) :: this
     204             :     integer :: get_ncol_lw
     205             : 
     206     2238408 :     if(this%is_allocated()) then
     207     2238408 :       get_ncol_lw = size(this%lay_source,1)
     208             :     else
     209             :       get_ncol_lw = 0
     210             :     end if
     211     2238408 :   end function get_ncol_lw
     212             :   ! --------------------------------------------------------------
     213     2238408 :   pure function get_nlay_lw(this)
     214             :     class(ty_source_func_lw), intent(in) :: this
     215             :     integer :: get_nlay_lw
     216             : 
     217     2238408 :     if(this%is_allocated()) then
     218     2238408 :       get_nlay_lw = size(this%lay_source,2)
     219             :     else
     220             :       get_nlay_lw = 0
     221             :     end if
     222     2238408 :   end function get_nlay_lw
     223             :   ! --------------------------------------------------------------
     224           0 :   pure function get_ncol_sw(this)
     225             :     class(ty_source_func_sw), intent(in) :: this
     226             :     integer :: get_ncol_sw
     227             : 
     228           0 :     if(this%is_allocated()) then
     229           0 :       get_ncol_sw = size(this%toa_source,1)
     230             :     else
     231             :       get_ncol_sw = 0
     232             :     end if
     233           0 :   end function get_ncol_sw
     234             :   ! ------------------------------------------------------------------------------------------
     235             :   !
     236             :   !  Routines for subsetting
     237             :   !
     238             :   ! ------------------------------------------------------------------------------------------
     239           0 :   function get_subset_range_lw(full, start, n, subset) result(err_message)
     240             :     class(ty_source_func_lw), intent(inout) :: full
     241             :     integer,                  intent(in   ) :: start, n
     242             :     class(ty_source_func_lw), intent(inout) :: subset
     243             :     character(128)                          :: err_message
     244             : 
     245           0 :     err_message = ""
     246           0 :     if(.not. full%is_allocated()) then
     247           0 :       err_message = "source_func_lw%subset: Asking for a subset of unallocated data"
     248           0 :       return
     249             :     end if
     250           0 :     if(start < 1 .or. start + n-1 > full%get_ncol()) &
     251           0 :        err_message = "optical_props%subset: Asking for columns outside range"
     252           0 :     if(err_message /= "") return
     253             : 
     254             :     !
     255             :     ! Could check to see if subset is correctly sized, has consistent spectral discretization
     256             :     !
     257           0 :     if(subset%is_allocated()) call subset%finalize()
     258           0 :     err_message = subset%alloc(n, full%get_nlay(), full)
     259           0 :     if(err_message /= "") return
     260           0 :     subset%sfc_source    (1:n,  :) = full%sfc_source    (start:start+n-1,  :)
     261           0 :     subset%sfc_source_Jac(1:n,  :) = full%sfc_source_Jac(start:start+n-1,  :)
     262           0 :     subset%lay_source    (1:n,:,:) = full%lay_source    (start:start+n-1,:,:)
     263           0 :     subset%lev_source_inc(1:n,:,:) = full%lev_source_inc(start:start+n-1,:,:)
     264           0 :     subset%lev_source_dec(1:n,:,:) = full%lev_source_dec(start:start+n-1,:,:)
     265             :   end function get_subset_range_lw
     266             :   ! ------------------------------------------------------------------------------------------
     267           0 :   function get_subset_range_sw(full, start, n, subset) result(err_message)
     268             :     class(ty_source_func_sw), intent(inout) :: full
     269             :     integer,                  intent(in   ) :: start, n
     270             :     class(ty_source_func_sw), intent(inout) :: subset
     271             :     character(128)                          :: err_message
     272             : 
     273           0 :     err_message = ""
     274           0 :     if(.not. full%is_allocated()) then
     275           0 :       err_message = "source_func_sw%subset: Asking for a subset of unallocated data"
     276           0 :       return
     277             :     end if
     278           0 :     if(start < 1 .or. start + n-1 > full%get_ncol()) &
     279           0 :        err_message = "optical_props%subset: Asking for columns outside range"
     280           0 :     if(err_message /= "") return
     281             : 
     282             :     !
     283             :     ! Could check to see if subset is correctly sized, has consistent spectral discretization
     284             :     !
     285           0 :     if(subset%is_allocated()) call subset%finalize()
     286             :     ! Seems like I should be able to call "alloc" generically but the compilers are complaining
     287           0 :     err_message = subset%copy_and_alloc_sw(n, full)
     288             : 
     289           0 :     subset%toa_source(1:n,  :) = full%toa_source(start:start+n-1,  :)
     290             :   end function get_subset_range_sw
     291           0 : end module mo_source_functions

Generated by: LCOV version 1.14