LCOV - code coverage report
Current view: | top level - atmos_phys/to_be_ccppized - coords_1d.F90 (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 40 | 51 | 78.4 %
Date: | 2024-12-17 17:57:11 |  | Functions: | 5 | 8 | 62.5 %

              Line data    Source code
           1             : module coords_1d
           2             :
           3             :     ! This module defines the Coords1D type, which is intended to to cache
           4             :     ! commonly used information derived from a collection of sets of 1-D
           5             :     ! coordinates.
           6             :
           7             :     use shr_kind_mod, only: r8 => shr_kind_r8
           8             :
           9             :     implicit none
          10             :     private
          11             :     save
          12             :
          13             :     public :: Coords1D
          14             :
          15             :     type :: Coords1D
          16             :        ! Number of sets of coordinates in the object.
          17             :        integer :: n = 0
          18             :        ! Number of coordinates in each set.
          19             :        integer :: d = 0
          20             :
          21             :        ! All fields below will be allocated with first dimension "n".
          22             :        ! The second dimension is d+1 for ifc, d for mid, del, and rdel, and
          23             :        ! d-1 for dst and rdst.
          24             :
          25             :        ! Cell interface coordinates.
          26             :        real(r8), allocatable :: ifc(:,:)
          27             :        ! Coordinates at cell mid-points.
          28             :        real(r8), allocatable :: mid(:,:)
          29             :        ! Width of cells.
          30             :        real(r8), allocatable :: del(:,:)
          31             :        ! Distance between cell midpoints.
          32             :        real(r8), allocatable :: dst(:,:)
          33             :        ! Reciprocals: 1/del and 1/dst.
          34             :        real(r8), allocatable :: rdel(:,:)
          35             :        real(r8), allocatable :: rdst(:,:)
          36             :      contains
          37             :        procedure :: section
          38             :        procedure :: finalize
          39             :     end type Coords1D
          40             :
          41             :     interface Coords1D
          42             :        module procedure new_Coords1D_from_fields
          43             :        module procedure new_Coords1D_from_int
          44             :     end interface
          45             :
          46             :     contains
          47             :
          48             :     ! Constructor to create an object from existing data.
          49           0 :     function new_Coords1D_from_fields(ifc, mid, del, dst, &
          50           0 :          rdel, rdst) result(coords)
          51             :       real(r8), USE_CONTIGUOUS intent(in) :: ifc(:,:)
          52             :       real(r8), USE_CONTIGUOUS intent(in) :: mid(:,:)
          53             :       real(r8), USE_CONTIGUOUS intent(in) :: del(:,:)
          54             :       real(r8), USE_CONTIGUOUS intent(in) :: dst(:,:)
          55             :       real(r8), USE_CONTIGUOUS intent(in) :: rdel(:,:)
          56             :       real(r8), USE_CONTIGUOUS intent(in) :: rdst(:,:)
          57             :       type(Coords1D) :: coords
          58             :
          59           0 :       coords = allocate_coords(size(ifc, 1), size(ifc, 2) - 1)
          60             :
          61           0 :       coords%ifc = ifc
          62           0 :       coords%mid = mid
          63           0 :       coords%del = del
          64           0 :       coords%dst = dst
          65           0 :       coords%rdel = rdel
          66           0 :       coords%rdst = rdst
          67             :
          68           0 :     end function new_Coords1D_from_fields
          69             :
          70             :     ! Constructor if you only have interface coordinates; derives all the other
          71             :     ! fields.
          72     8935056 :     function new_Coords1D_from_int(ifc) result(coords)
          73             :       real(r8), USE_CONTIGUOUS intent(in) :: ifc(:,:)
          74             :       type(Coords1D) :: coords
          75             :
          76     4467528 :       coords = allocate_coords(size(ifc, 1), size(ifc, 2) - 1)
          77             :
          78  7021083888 :       coords%ifc = ifc
          79  6946486560 :       coords%mid = 0.5_r8 * (ifc(:,:coords%d)+ifc(:,2:))
          80  6946486560 :       coords%del = coords%ifc(:,2:) - coords%ifc(:,:coords%d)
          81  6871889232 :       coords%dst = coords%mid(:,2:) - coords%mid(:,:coords%d-1)
          82  6946486560 :       coords%rdel = 1._r8/coords%del
          83  6871889232 :       coords%rdst = 1._r8/coords%dst
          84             :
          85     4467528 :     end function new_Coords1D_from_int
          86             :
          87             :     ! Create a new Coords1D object that is a subsection of some other object,
          88             :     ! e.g. if you want only the first m coordinates, use d_bnds=[1, m].
          89             :     !
          90             :     ! Originally this used pointers, but it was found to actually be cheaper
          91             :     ! in practice just to make a copy, especially since pointers can impede
          92             :     ! optimization.
          93    19359288 :     function section(self, n_bnds, d_bnds)
          94             :       class(Coords1D), intent(in) :: self
          95             :       integer, intent(in) :: n_bnds(2), d_bnds(2)
          96             :       type(Coords1D) :: section
          97             :
          98    19359288 :       section = allocate_coords(n_bnds(2)-n_bnds(1)+1, d_bnds(2)-d_bnds(1)+1)
          99             :
         100 28531058622 :       section%ifc = self%ifc(n_bnds(1):n_bnds(2),d_bnds(1):d_bnds(2)+1)
         101 28207803534 :       section%mid = self%mid(n_bnds(1):n_bnds(2),d_bnds(1):d_bnds(2))
         102 28207803534 :       section%del = self%del(n_bnds(1):n_bnds(2),d_bnds(1):d_bnds(2))
         103 27884548446 :       section%dst = self%dst(n_bnds(1):n_bnds(2),d_bnds(1):d_bnds(2)-1)
         104 28207803534 :       section%rdel = self%rdel(n_bnds(1):n_bnds(2),d_bnds(1):d_bnds(2))
         105 27884548446 :       section%rdst = self%rdst(n_bnds(1):n_bnds(2),d_bnds(1):d_bnds(2)-1)
         106             :
         107    19359288 :     end function section
         108             :
         109             :     ! Quick utility to get allocate each array with the correct size.
         110    23826816 :     function allocate_coords(n, d) result(coords)
         111             :       integer, intent(in) :: n, d
         112             :       type(Coords1D) :: coords
         113             :
         114    23826816 :       coords%n = n
         115    23826816 :       coords%d = d
         116             :
         117    95307264 :       allocate(coords%ifc(coords%n,coords%d+1))
         118    95307264 :       allocate(coords%mid(coords%n,coords%d))
         119    71480448 :       allocate(coords%del(coords%n,coords%d))
         120    95307264 :       allocate(coords%dst(coords%n,coords%d-1))
         121    71480448 :       allocate(coords%rdel(coords%n,coords%d))
         122    71480448 :       allocate(coords%rdst(coords%n,coords%d-1))
         123             :
         124    23826816 :     end function allocate_coords
         125             :
         126             :     ! Deallocate and reset to initial state.
         127     4467528 :     subroutine finalize(self)
         128             :       class(Coords1D), intent(inout) :: self
         129             :
         130     4467528 :       self%n = 0
         131     4467528 :       self%d = 0
         132             :
         133     4467528 :       call guarded_deallocate(self%ifc)
         134     4467528 :       call guarded_deallocate(self%mid)
         135     4467528 :       call guarded_deallocate(self%del)
         136     4467528 :       call guarded_deallocate(self%dst)
         137     4467528 :       call guarded_deallocate(self%rdel)
         138     4467528 :       call guarded_deallocate(self%rdst)
         139             :
         140             :     contains
         141             :
         142    26805168 :       subroutine guarded_deallocate(array)
         143             :         real(r8), allocatable :: array(:,:)
         144             :
         145    26805168 :         if (allocated(array)) deallocate(array)
         146             :
         147    26805168 :       end subroutine guarded_deallocate
         148             :
         149             :     end subroutine finalize
         150             :
         151           0 : end module coords_1d
         152             :

Generated by: LCOV version 1.14