module analysis_interface !======================================================================= !$$$ MODULE DOCUMENTATION BLOCK ! da-update-analysis :: analysis_interface ! Copyright (C) 2018 Henry R. Winterbottom ! Email: henry.winterbottom@noaa.gov ! This program is free software: you can redistribute it and/or ! modify it under the terms of the GNU General Public License as ! published by the Free Software Foundation, either version 3 of the ! License, or (at your option) any later version. ! This program is distributed in the hope that it will be useful, ! but WITHOUT ANY WARRANTY; without even the implied warranty of ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! General Public License for more details. ! You should have received a copy of the GNU General Public License ! along with this program. If not, see ! <http://www.gnu.org/licenses/>. !======================================================================= ! Define associated modules and subroutines use constants_interface use f95_precision use fileio_interface use interpolation_interface use math_methods_interface use namelist_interface use variable_interface ! Define interfaces and attributes for module routines implicit none private public :: analysis_increment public :: blend_interface_boundary public :: blend_interface_cycling public :: blend_interface_nest public :: blend_interface_radii public :: blend_interface_tc_environment public :: blend_interface_wnd !----------------------------------------------------------------------- contains !======================================================================= ! SUBROUTINE: ! analysis_increment.f90 ! DESCRIPTION: ! This subroutine computes the increment applied to the first-guess ! (i.e., background) forecast variable, usually via a data ! assimilative methodology, to define the analysis (e.g., state) ! variable; this subroutine assumes that the first-guess and ! analysis variables, used to compute the increment values, are ! defined on identical grid projections. ! INPUT VARIABLES: ! * fg_grid; a FORTRAN grid_struct variable containing the ! first-guess (e.g., background) forecast variable. ! * an_grid; a FORTRAN grid_struct variable containing the analysis ! (i.e., the data-assimialtion updated state) variable. ! * ic_grid; a FORTRAN grid_struct variable to contain the ! increments (e.g., analysis - background) variable. ! OUTPUT VARIABLES: ! * ic_grid; a FORTRAN grid_struct variable containing the ! increments applied to the first-guess forecast variable to ! define the respective analysis variable as well as the ! first-guess grid projection. !----------------------------------------------------------------------- subroutine analysis_increment(fg_grid,an_grid,ic_grid) ! Define variables passed to routine type(grid_struct) :: an_grid type(grid_struct) :: fg_grid type(grid_struct) :: ic_grid ! Define counting variables integer :: i !===================================================================== ! Define local variables ic_grid%nx = fg_grid%nx ic_grid%ny = fg_grid%ny ic_grid%nz = fg_grid%nz call variable_interface_setup_struct(ic_grid) ! Loop through local variable do i = 1, ic_grid%nz ! Compute local variables ic_grid%var(:,i) = (an_grid%var(:,i) - fg_grid%var(:,i)) end do ! do i = 1, ic_grid%nz !===================================================================== end subroutine analysis_increment !======================================================================= ! SUBROUTINE: ! blend_interface_boundary.f90 ! DESCRIPTION: ! This subroutine blends two analysis variables; the projections for ! the input and output grids (in_grid and out_grid, respectively) ! are assumed identical; the user configuration defines the region ! within the input grid to merge (e.g., blend) the analysis (see ! namelist variable npts_blend) and the number of points within the ! merge region to relax to the output grid variable. ! INPUT VARIABLES: ! * in_grid; a FORTRAN grid_struct variable containing the input ! grid projection and variable to be relaxed to the output ! variable. ! * out_grid; a FORTRAN grid_struct variable containing the output ! grid projection and the variable to be relaxed to at the edges ! of the blending (e.g., merge) region. ! OUTPUT VARIABLES: ! * out_grid; a FORTRAN grid_struct variable containing the merged ! (e.g., blended) variable. !----------------------------------------------------------------------- subroutine blend_interface_boundary(in_grid,out_grid) ! Define variables passed to routine type(grid_struct) :: in_grid type(grid_struct) :: out_grid ! Define variables computed within routine type(blend_struct) :: blend type(merge_struct) :: merge type(slint_struct) :: slint real(r_kind), dimension(:,:,:), allocatable :: in_work real(r_kind), dimension(:,:,:), allocatable :: out_work integer :: dst_idx integer :: bmnx integer :: bmny integer :: bmxx integer :: bmxy integer :: rmnx integer :: rmny integer :: rmxx integer :: rmxy ! Define counting variables integer :: i, j, k !===================================================================== ! Allocate memory for local variables if(.not. allocated(in_work)) & & allocate(in_work(in_grid%nx,in_grid%ny,in_grid%nz)) if(.not. allocated(out_work)) & & allocate(out_work(out_grid%nx,out_grid%ny,out_grid%nz)) ! Define local variables bmnx = min(npts_blend,in_grid%nx) bmny = min(npts_blend,in_grid%ny) bmxx = max((in_grid%nx - npts_blend),1) bmxy = max((in_grid%ny - npts_blend),1) rmnx = min(max(bmnx,(bmnx + npts_relax)),in_grid%nx) rmny = min(max(bmny,(bmny + npts_relax)),in_grid%ny) rmxx = max(min(bmxx,(bmxx - npts_relax)),1) rmxy = max(min(bmxy,(bmxy - npts_relax)),1) merge%bmnx = bmnx merge%bmxx = bmxx merge%bmny = bmny merge%bmxy = bmxy merge%rmnx = rmnx merge%rmxx = rmxx merge%rmny = rmny merge%rmxy = rmxy merge%nx = in_grid%nx merge%ny = in_grid%ny merge%nz = in_grid%nz call variable_interface_setup_struct(merge) merge%lat_an = out_grid%lat merge%lon_an = out_grid%lon merge%lat_fg = in_grid%lat merge%lon_fg = in_grid%lon ! Loop through local variable do k = 1, out_grid%nz ! Define local variables in_work(:,:,k) = reshape(in_grid%var(:,k),shape(in_work(:,:,k))) out_work(:,:,k) = reshape(out_grid%var(:,k), & & shape(out_work(:,:,k))) ! Loop through local variable do j = rmny, rmxy ! Loop through local variable do i = rmnx, rmxx ! Define local variables in_work(i,j,k) = out_work(i,j,k) end do ! do i = rmnx, rmxx end do ! do j = rmny, rmxy ! Loop through local variable do j = rmny, rmxy ! Loop through local variable do i = bmnx, rmnx ! Define local variables in_work(i,j,k) = spval end do ! do i = bmnx, rmnx ! Loop through local variable do i = rmxx, bmxx ! Define local variables in_work(i,j,k) = spval end do ! do i = rmxx, bmxx end do ! do j = bmny, rmny ! Loop through local variable do i = rmnx, rmxx ! Loop through local variable do j = bmny, rmny ! Define local variables in_work(i,j,k) = spval end do ! do j = bmny, rmny ! Loop through local variable do j = rmxy, bmxy ! Define local variables in_work(i,j,k) = spval end do ! do j = rmxy, bmxy end do ! do i = rmnx, rmxx ! Define local variables in_grid%var(:,k) = reshape(in_work(:,:,k),shape(in_grid%var(:,k))) end do ! do k = 1, out_grid%nz ! Define local variables merge%npts_blend = npts_blend merge%npts_relax = npts_relax merge%var = in_grid%var call define_mask_boundary(merge) merge%var_fg = in_grid%var merge%var_an = out_grid%var blend%nx = merge%nx blend%ny = merge%ny blend%nz = merge%nz call variable_interface_setup_struct(blend) blend%lat = merge%lat_an blend%lon = merge%lon_an blend%mask = merge%mask blend%npts_blend = merge%npts_blend blend%npts_relax = merge%npts_relax ! Loop through local variable do j = 1, blend%nz ! Define local variables blend%var(:,j) = merge%var_fg(:,j) where(blend%var(:,j) .eq. spval) blend%var(:,j) = & & merge%var_an(:,j) end do ! do j = 1, blend%nz ! Define local variables blend%var_blend = blend%var ! Loop through local variable do k = 1, (blend%npts_blend + blend%npts_relax) ! Compute local variables if(is_slint) call grid_blend(blend,slint,real(k)) ! Loop through local variable do j = 1, blend%nz ! Compute local variables if(is_slint) call interpolation_interface_bilinear(slint, & & blend%var(:,j)) ! Loop through local variable do i = 1, blend%ncoords ! Define local variables dst_idx = blend%idx(i) ! Check local variable and proceed accordingly if((dst_idx .gt. 0) .and. (dst_idx .le. (blend%nx*blend%ny)) & & .and. (size(slint%var) .gt. 0)) then ! Check local variable and proceed accordingly if(is_slint) then ! Define local variables blend%var_blend(i,j) = slint%var(dst_idx) end if ! if(is_slint) end if ! if((dst_idx .gt. 0) .and. (dst_idx ! .le. (blend%nx*blend%ny)) .and. (size(slint%var) ! .gt. 0)) end do ! do i = 1, blend%ncoords end do ! do j = 1, blend%nz ! Define local variables where(blend%mask .eq. real(k)) blend%mask = spval blend%idx = -999 ! Deallocate memory for local variables call variable_interface_cleanup_struct(slint) end do ! do k = 1, (blend%npts_blend + blend%npts_relax) ! Define local variables out_grid%var = blend%var_blend ! Deallocate memory for local variables if(allocated(in_work)) deallocate(in_work) if(allocated(out_work)) deallocate(out_work) call variable_interface_cleanup_struct(merge) call variable_interface_cleanup_struct(blend) !===================================================================== end subroutine blend_interface_boundary !======================================================================= ! SUBROUTINE: ! blend_interface_cycling.f90 ! DESCRIPTION: ! This subroutine merges two domains, of identical dimensions, using ! a relaxation blending mask for the overlapping regions. ! INPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable; it is assumed that all ! arrays within the structure and the respective blending ! attributes have been specified before calling this routine; ! also, the lat_an, lon_an, lat_fg, lon_fg, var_an and var_fg ! attribute arrays have also been populated. ! OUTPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable containing the merged ! grid variable. !----------------------------------------------------------------------- subroutine blend_interface_cycling(merge) ! Define variables passed to routine type(merge_struct) :: merge ! Define counting variables integer :: i !===================================================================== ! Define local variables merge%var = merge%var_an ! Compute local variables call define_overlap_mask(merge) ! Loop through local variable do i = 1, merge%nz ! Define local variables merge%var(:,i) = merge%var_fg(:,i)*merge%mask + & & merge%var_an(:,i)*(1.0 - merge%mask) end do ! do i = 1, merge%nz !===================================================================== end subroutine blend_interface_cycling !======================================================================= ! SUBROUTINE: ! blend_interface_nest.f90 ! DESCRIPTION: ! This subroutine blends a nested grid within the parent grid region ! using an interative interpolation method; this method interpolates ! from outer to inner; an optional 9-point smoothing algorithm may ! be applied to smooth any gradients which may arise from large ! discontinuities between nested/blended variable fields. ! INPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable; it is assumed that all ! arrays within the structure and the respective blending ! attributes have been specified before calling this routine; ! also, the var_fixed and var_blend attribute arrays have also ! been populated. ! OUTPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable containing the blended ! nest and parent grid variables. !----------------------------------------------------------------------- subroutine blend_interface_nest(blend) ! Define variables passed to routine type(blend_struct) :: blend ! Define variables computed within routine type(grid_struct) :: grid real(r_kind), dimension(:), allocatable :: mask_relax real(r_kind), dimension(:), allocatable :: nest_incr ! Define counting variables integer :: i !===================================================================== ! Define local variables grid%nx = blend%nx grid%ny = blend%ny call variable_interface_setup_struct(grid) grid%lat = blend%lat grid%lon = blend%lon ! Compute local variables call math_methods_polarcoords(grid,blend%clon,blend%clat) ! Allocate memory for local variables if(.not. allocated(mask_relax)) allocate(mask_relax(blend%ncoords)) if(.not. allocated(nest_incr)) allocate(nest_incr(blend%ncoords)) ! Define local variables mask_relax = (grid%radius - blend%tc_nest_min_radius)/ & & (blend%tc_nest_max_radius - blend%tc_nest_min_radius) where(mask_relax .le. 0.0) mask_relax = 0.0 where(mask_relax .ge. 1.0) mask_relax = 1.0 mask_relax = 1.0 - mask_relax ! Loop through local variable do i = 1, blend%nz ! Define local variables nest_incr = blend%var_fixed(:,i)*(1.0 - mask_relax) & & + blend%var_blend(:,i)*mask_relax blend%var_blend(:,i) = nest_incr end do ! do i = 1, blend%nz ! Deallocate memory for local variables if(allocated(mask_relax)) deallocate(mask_relax) if(allocated(nest_incr)) deallocate(nest_incr) call variable_interface_cleanup_struct(grid) !===================================================================== end subroutine blend_interface_nest !======================================================================= ! SUBROUTINE: ! blend_interface_radii.f90 ! DESCRIPTION: ! This subroutine computes the nest to parent blending radii ! thresholds; the radii are determined by the minimum value(s) for ! the maximum nest radii and then scaled according to the namelist ! parameter tc_nest_ratio_blend. ! INPUT VARIABLES: ! * grid; a FORTRAN grid_struct variable containing the nested-grid ! and it's respective grid projection attributes. ! * blend; a FORTRAN blend_struct variable. ! OUTPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable containing the threshold ! variable values to be used for blending the nest and parent ! domain co-located regions (see the tc_nest_max_radius and ! tc_nest_min_radius attributes). !----------------------------------------------------------------------- subroutine blend_interface_radii(grid,blend) ! Define variables passed to routine type(blend_struct) :: blend type(grid_struct) :: grid ! Define variables computed within routine real(r_kind), dimension(:,:), allocatable :: radius real(r_kind) :: maxradii ! Define counting variables integer :: i !===================================================================== ! Compute local variables call math_methods_polarcoords(grid,blend%clon,blend%clat) ! Allocate memory for local variables if(.not. allocated(radius)) allocate(radius(grid%nx,grid%ny)) ! Define local variables radius = reshape(grid%radius,shape(radius)) maxradii = rearth_equator ! Loop through local variable do i = 1, grid%nx ! Define local variables maxradii = min(maxradii,maxval(radius(i,:))) end do ! do i = 1, grid%nx ! Loop through local variable do i = 1, grid%ny ! Define local variables maxradii = min(maxradii,maxval(radius(:,i))) end do ! do i = 1, grid%ny ! Define local variables blend%tc_nest_max_radius = maxradii blend%tc_nest_min_radius = blend%tc_nest_max_radius* & & tc_nest_ratio_blend ! Deallocate memory for local variables if(allocated(radius)) deallocate(radius) !===================================================================== end subroutine blend_interface_radii !======================================================================= ! SUBROUTINE: ! blend_interface_tc_environment.f90 ! DESCRIPTION: ! This subroutine blends the an analysis variable field with a ! first-guess variable (e.g., environmental) field. ! INPUT VARIABLES: ! * grid_fg; a FORTRAN grid_struct variable containing the ! first-guess variable (and it's respective grid projection ! attributes). ! * grid_an; a FORTRAN grid_struct variable containing the analysis ! variable (and it's respective grid projection attributes) which ! to blend in accordance with the user specifications. ! OUTPUT VARIABLES: ! * grid_an; a FORTRAN grid_struct variable containing the analysis ! variable blended, for each TC, in accordance with the user ! specifications. !----------------------------------------------------------------------- subroutine blend_interface_tc_environment(grid_fg,grid_an) ! Define variables passed to routine type(grid_struct) :: grid_an type(grid_struct) :: grid_fg ! Define variables computed within routine type(tcv_struct), dimension(:), allocatable :: tcv type(grid_struct) :: dst_grid type(grid_struct) :: dst_sub_grid type(grid_struct) :: src_grid ! Define counting variables integer :: i, j !===================================================================== ! Define local variables call fileio_interface_read(tcv_filename,tcv) dst_grid%nx = grid_an%nx dst_grid%ny = grid_an%ny dst_grid%nz = grid_an%nz call variable_interface_setup_struct(dst_grid) dst_grid%lat = grid_an%lat dst_grid%lon = grid_an%lon dst_grid%var = grid_fg%var ! Check local variable and proceed accordingly if(ic_blend_opt .ne. 0) then ! Loop through local variable do i = 1, size(tcv) ! Compute local variables call math_methods_polarcoords(dst_grid,tcv(i)%lon,tcv(i)%lat) ! Loop through local variable do j = 1, grid_an%nz ! Define local variables where(dst_grid%radius .lt. & & ((1.0 - region_blend_ratio)*tc_large_scale_radius)) & & dst_grid%var(:,j) = grid_an%var(:,j) where(dst_grid%radius .ge. & & ((1.0 - region_blend_ratio)*tc_large_scale_radius)) & & dst_grid%var(:,j) = spval where(dst_grid%radius .gt. tc_large_scale_radius) & & dst_grid%var(:,j) = grid_fg%var(:,j) end do ! do j = 1, grid_an%nz ! Compute local variables call environment_blend(dst_grid,grid_an,grid_fg) ! Define local variables grid_an%var = dst_grid%var end do ! do i = 1, size(tcv) end if ! if(ic_blend_opt .ne. 0) ! Deallocate memory for local variables if(allocated(tcv)) deallocate(tcv) call variable_interface_cleanup_struct(dst_grid) !===================================================================== end subroutine blend_interface_tc_environment !======================================================================= ! SUBROUTINE: ! blend_interface_wnd.f90 ! DESCRIPTION: ! This subroutine blends the analysis increments surrounding ! tropical cyclone (TC) events in accordance with the user ! specifications; this subroutine currently supports the following ! methods (e.g., ic_blend_opt values): ! 1: compute the wavenumber spectra for the respective variable and ! blend only up to and including the maximum wavenumber specified ! by the user (wndcmp_mxwvn). ! 2: set all variable values within the user specified TC inner-core ! radius to zero. ! INPUT VARIABLES: ! * grid; a FORTRAN grid_struct variable containing the analysis ! increment variable (and it's respective grid projection ! attributes) which to blend in accordance with the user ! specifications. ! OUTPUT VARIABLES: ! * grid; a FORTRAN grid_struct variable containing the analysis ! increment variable blended, for each TC, in accordance with the ! user specifications. !----------------------------------------------------------------------- subroutine blend_interface_wnd(grid) ! Define variables passed to routine type(grid_struct) :: grid ! Define variables computed within routine type(tcv_struct), dimension(:), allocatable :: tcv type(grid_struct) :: dst_grid type(grid_struct) :: dst_sub_grid type(grid_struct) :: src_grid ! Define counting variables integer :: i, j !===================================================================== ! Define local variables call fileio_interface_read(tcv_filename,tcv) dst_grid%nx = grid%nx dst_grid%ny = grid%ny dst_grid%nz = grid%nz call variable_interface_setup_struct(dst_grid) dst_grid%lat = grid%lat dst_grid%lon = grid%lon ! Check local variable and proceed accordingly if(ic_blend_opt .ne. 0) then ! Loop through local variable do i = 1, size(tcv) ! Compute local variables call math_methods_polarcoords(dst_grid,tcv(i)%lon,tcv(i)%lat) ! Define local variables grid%radius = dst_grid%radius ! Compute local variables if(ic_blend_opt .eq. 1) call wnd2d_tc_increment(grid,tcv(i), & & dst_grid) if(ic_blend_opt .eq. 2) call zero_tc_increment(grid,dst_grid) call region_blend(dst_grid,grid) end do ! do i = 1, size(tcv) end if ! if(ic_blend_opt .ne. 0) ! Deallocate memory for local variables if(allocated(tcv)) deallocate(tcv) call variable_interface_cleanup_struct(dst_grid) !===================================================================== end subroutine blend_interface_wnd !======================================================================= ! SUBROUTINE: ! define_mask_boundary.f90 ! DESCRIPTION: ! This subroutine defines the blending mask used to merge two ! identical dimension grid variables along the boundary edges. ! INPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable; it is assumed that all ! arrays within the structure and the respective blending ! attributes have been specified before calling this routine. ! OUTPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable containing the merging ! and blending mask regions. !----------------------------------------------------------------------- subroutine define_mask_boundary(merge) ! Define variables passed to routine type(merge_struct) :: merge ! Define variables computed within routine type(blend_struct) :: blend !===================================================================== ! Define local variables merge%mask = 1.0 where(merge%var(:,1) .eq. spval) merge%mask = -1.0 blend%nx = merge%nx blend%ny = merge%ny blend%nz = merge%nz blend%bmnx = merge%bmnx blend%bmxx = merge%bmxx blend%bmny = merge%bmny blend%bmxy = merge%bmxy blend%rmnx = merge%rmnx blend%rmxx = merge%rmxx blend%rmny = merge%rmny blend%rmxy = merge%rmxy call variable_interface_setup_struct(blend) blend%npts_relax = merge%npts_relax blend%npts_blend = merge%npts_blend blend%mask = merge%mask call mask_relax_boundary(blend) merge%mask = blend%mask merge%idx = -999 ! Deallocate memory for local variables call variable_interface_cleanup_struct(blend) !===================================================================== end subroutine define_mask_boundary !======================================================================= ! SUBROUTINE: ! define_mask_merge.f90 ! DESCRIPTION: ! This subroutine defines the blending mask used to merge two ! identical dimension grid variables. ! INPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable; it is assumed that all ! arrays within the structure and the respective blending ! attributes have been specified before calling this routine. ! OUTPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable containing the merging ! and blending mask regions. !----------------------------------------------------------------------- subroutine define_mask_merge(merge) ! Define variables passed to routine type(merge_struct) :: merge ! Define variables computed within routine real(r_kind) :: mnlat_fg real(r_kind) :: mnlon_fg real(r_kind) :: mxlat_fg real(r_kind) :: mxlon_fg !===================================================================== ! Define local variables call init_mask_merge(merge) call mask_relax_merge(merge) merge%idx = -999 !===================================================================== end subroutine define_mask_merge !======================================================================= ! SUBROUTINE: ! define_overlap_mask.f90 ! DESCRIPTION ! This subroutine determines the overlap regions for a two ! respective domains (e.g., the first-guess denoted by 'fg' and the ! analysis denoted by 'an') and defines a relaxation mask of width ! 'npts_relax' as specified in the FORTRAN merge_struct variable. ! INPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable; it is assumed that all ! arrays within the structure and the respective blending ! attributes have been specified before calling this routine. ! OUTPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable containing the merging ! and blending mask regions. !----------------------------------------------------------------------- subroutine define_overlap_mask(merge) ! Define variables passed to routine type(merge_struct) :: merge ! Define variables computed within routine type(grid_struct) :: grid_an type(grid_struct) :: grid_fg type(kdtree_struct) :: kdtree real(r_kind), dimension(:,:), allocatable :: mask real(r_kind), dimension(:,:), allocatable :: mask_save real(r_kind) :: r2dist real(r_kind) :: maxdist integer :: icoord integer :: idx_strt integer :: idx_stop integer :: strt_idx integer :: stop_idx ! Define counting variables integer :: i, j, k !===================================================================== ! Define local variables grid_an%nx = merge%nx grid_an%ny = merge%ny call variable_interface_setup_struct(grid_an) grid_an%lat = merge%lat_an grid_an%lon = merge%lon_an grid_fg%nx = merge%nx grid_fg%ny = merge%ny call variable_interface_setup_struct(grid_fg) grid_fg%lat = merge%lat_fg grid_fg%lon = merge%lon_fg kdtree%ncoords = (merge%nx*merge%ny) kdtree%nn = 1 call variable_interface_setup_struct(kdtree) merge%mask = spval ! Compute local variables call math_methods_kdtree_nn(grid_fg,grid_an,kdtree) ! Define local variables maxdist = -spval ! Loop through local variable do i = 1, merge%ncoords ! Compute local variables r2dist = sqrt(merge%dx(i)*merge%dx(i) + merge%dy(i)*merge%dy(i)) ! Define local variables maxdist = max(maxdist,r2dist) end do ! do i = 1, merge%ncoords ! Define local variables where(sqrt(kdtree%r2dist(:,1)) .gt. maxdist) merge%mask = 1.0 ! Allocate memory for local variables if(.not. allocated(mask)) allocate(mask(merge%nx,merge%ny)) if(.not. allocated(mask_save)) allocate(mask_save(merge%nx,merge%ny)) ! Define local variables mask = reshape(merge%mask,shape(mask)) mask_save = mask ! Loop through local variable do j = 1, merge%ny ! Define local variables idx_strt = imin idx_stop = imax ! Loop through local variable do i = 1, merge%nx ! Check local variable and proceed accordingly if(mask(i,j) .eq. spval) idx_strt = min(idx_strt,i) if(mask(i,j) .eq. 1.0) idx_stop = max(idx_stop,i) end do ! do i = 1, merge%nx ! Check local variable and proceed accordingly if((idx_stop .ne. imax) .and. (idx_strt .ne. imin) .and. (idx_strt & & .ne. 1) .and. (idx_stop .ne. merge%nx)) then ! Define local variables icoord = 1 strt_idx = min((idx_strt + merge%npts_relax),merge%nx) stop_idx = idx_strt icoord = strt_idx ! Loop through local variable do while (icoord .ge. stop_idx) ! Define local variables mask_save(stop_idx:icoord,j) = 1.0 - (real(icoord) - & & real(stop_idx))/(real(strt_idx) - real(stop_idx)) icoord = icoord - 1 end do ! do while (icoord .le. stop_idx) end if ! if((idx_stop .ne. imax) .and. (idx_strt .ne. imin) ! .and. (idx_strt .ne. 1) .and. (idx_stop ! .ne. merge%nx)) end do ! do j = 1, merge%ny ! Loop through local variable do j = 1, merge%ny ! Define local variables idx_strt = imax idx_stop = imin ! Loop through local variable do i = 1, merge%nx ! Check local variable and proceed accordingly if(mask(i,j) .eq. spval) idx_strt = max(idx_strt,i) if(mask(i,j) .eq. 1.0) idx_stop = min(idx_stop,i) end do ! do i = 1, merge%nx ! Check local variable and proceed accordingly if((idx_stop .ne. imin) .and. (idx_strt .ne. imax) .and. (idx_strt & & .ne. merge%nx) .and. (idx_stop .ne. 1)) then ! Define local variables icoord = 1 strt_idx = max((idx_stop - merge%npts_relax),1) stop_idx = idx_stop icoord = strt_idx ! Loop through local variable do while (icoord .le. stop_idx) ! Define local variables mask_save(icoord:stop_idx,j) = 1.0 - (real(icoord) - & & real(stop_idx))/(real(strt_idx) - real(stop_idx)) icoord = icoord + 1 end do ! do while (icoord .le. stop_idx) end if ! if((idx_stop .ne. imin) .and. (idx_strt .ne. imax) ! .and. (idx_strt .ne. merge%nx) .and. (idx_stop ! .ne. 1)) end do ! do j = 1, merge%ny ! Loop through local variable do i = 1, merge%nx ! Define local variables idx_strt = imin idx_stop = imax ! Loop through local variable do j = 1, merge%ny ! Check local variable and proceed accordingly if(mask(i,j) .eq. spval) idx_strt = min(idx_strt,j) if(mask(i,j) .eq. 1.0) idx_stop = max(idx_stop,j) end do ! do j = 1, merge%ny ! Check local variable and proceed accordingly if((idx_stop .ne. imax) .and. (idx_strt .ne. imin) .and. (idx_stop & & .ne. merge%ny) .and. (idx_strt .ne. 1)) then ! Define local variables icoord = 1 strt_idx = min((idx_strt + merge%npts_relax),merge%ny) stop_idx = idx_strt icoord = strt_idx ! Loop through local variable do while (icoord .ge. stop_idx) ! Define local variables mask_save(i,stop_idx:icoord) = 1.0 - (real(stop_idx) - & & real(icoord))/(real(stop_idx) - real(strt_idx)) icoord = icoord - 1 end do ! do while (icoord .le. stop_idx) end if ! if((idx_stop .ne. imax) .and. (idx_strt .ne. imin) ! .and. (idx_stop .ne. merge%ny) .and. (idx_strt ! .ne. 1)) end do ! do i = 1, merge%nx ! Loop through local variable do i = 1, merge%nx ! Define local variables idx_strt = imax idx_stop = imin ! Loop through local variable do j = 1, merge%ny ! Check local variable and proceed accordingly if(mask(i,j) .eq. spval) idx_strt = max(idx_strt,j) if(mask(i,j) .eq. 1.0) idx_stop = min(idx_stop,j) end do ! do j = 1, merge%ny ! Check local variable and proceed accordingly if((idx_stop .ne. imax) .and. (idx_strt .ne. imin) .and. (idx_stop & & .ne. 1) .and. (idx_strt .ne. merge%ny)) then ! Define local variables icoord = 1 strt_idx = max((idx_stop - merge%npts_relax),1) stop_idx = idx_stop icoord = strt_idx ! Loop through local variable do while (icoord .le. stop_idx) ! Define local variables mask_save(i,icoord:stop_idx) = 1.0 - (real(icoord) - & & real(stop_idx))/(real(strt_idx) - real(stop_idx)) icoord = icoord + 1 end do ! do while (icoord .le. stop_idx) end if ! if((idx_stop .ne. imax) .and. (idx_strt .ne. imin) ! .and. (idx_stop .ne. 1) .and. (idx_strt ! .ne. merge%ny)) end do ! do i = 1, merge%nx ! Define local variables merge%mask = reshape(mask_save,shape(merge%mask)) where(merge%mask .eq. spval) merge%mask = 0.0 where(merge%mask .gt. 1.0) merge%mask = 1.0 where(merge%mask .lt. 0.0) merge%mask = 0.0 ! Deallocate memory for local variables if(allocated(mask)) deallocate(mask) if(allocated(mask_save)) deallocate(mask_save) call variable_interface_cleanup_struct(grid_an) call variable_interface_cleanup_struct(grid_fg) call variable_interface_cleanup_struct(kdtree) !===================================================================== end subroutine define_overlap_mask !======================================================================= ! SUBROUTINE: ! environment_blend.f90 ! DESCRIPTION: ! This subroutine blends values to fill a missing data region ! (signified by a value of 'spval') within the input variable grid ! (in_grid) and fills the respective locations (determined via ! interpolation) using the analysis and first-guess variable arrays ! (within the respective an_grid and fg_grid FORTRAN grid_struct ! variables) to relax the regional values into the environmental ! values. ! INPUT VARIABLES: ! * dst_grid; a FORTRAN grid_struct variable containing a region to ! be populated via linear-interpolation. ! * grid_an; a FORTRAN grid_struct variable containing the analysis ! variable attributes. ! * grid_fg; a FORTRAN grid_struct variable containing the ! first-guess variable attributes. ! OUTPUT VARIABLES: ! * an_grid; a FORTRAN grid_struct variable containing analysis ! variable values where the input grid values are determined via ! linear-interpolation. !----------------------------------------------------------------------- subroutine environment_blend(dst_grid,grid_an,grid_fg) ! Define variables passed to routine type(grid_struct) :: dst_grid type(grid_struct) :: grid_an type(grid_struct) :: grid_fg ! Define variables computed within routine real(r_kind) :: mask_relax ! Define counting variables integer :: i, j !===================================================================== ! Loop through local variable do j = 1, grid_an%nz ! Define local variables where(dst_grid%radius .le. tc_ic_radius) dst_grid%var(:,j) = & & grid_an%var(:,j) where(dst_grid%radius .ge. tc_large_scale_radius) & & dst_grid%var(:,j) = grid_fg%var(:,j) ! Loop through local variable do i = 1, grid_an%ncoords ! Check local variable and proceed accordingly if((dst_grid%radius(i) .gt. tc_ic_radius) .and. & & (dst_grid%radius(i) .lt. tc_large_scale_radius)) then ! Define local variables mask_relax = (dst_grid%radius(i) - tc_ic_radius)/ & & (tc_large_scale_radius - tc_ic_radius) dst_grid%var(i,j) = grid_an%var(i,j)*(1.0 - mask_relax) + & & grid_fg%var(i,j)*mask_relax end if ! if((dst_grid%radius(i) .gt. tc_ic_radius) ! .and. (dst_grid%radius(i) ! .lt. tc_large_scale_radius) end do ! do i = 1, grid_an%ncoords end do ! do j = 1, grid_an%nz !===================================================================== end subroutine environment_blend !======================================================================= ! SUBROUTINE: ! grid_blend.f90 ! DESCRIPTION: ! This subroutine defines the remapping attributes required to blend ! two grids together. ! INPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable; it is assumed that all ! arrays within the structure and the respective blending ! attributes have been specified before calling this routine. ! * slint; a FORTRAN slint_struct variable; only utilized if SLINT ! interpolation is specified by the user. ! * mask; a FORTRAN 4-byte real variable specifying the mask value ! for which to interpolate. ! OUTPUT VARIABLES: ! * slint; a FORTRAN slint_struct variable containing the SLINT ! defined remapping attributes if SLINT interpolation is specified ! by the user. !----------------------------------------------------------------------- subroutine grid_blend(blend,slint,mask) ! Define variables passed to routine type(blend_struct) :: blend type(slint_struct) :: slint real(r_kind) :: mask ! Define variables computed within routine type(grid_struct) :: dst_grid type(grid_struct) :: src_grid integer :: dst_ncoords integer :: src_ncoords ! Define counting variables integer :: i !===================================================================== ! Define local variables src_grid%ncoords = count(blend%mask .eq. spval) src_grid%nz = 1 call variable_interface_setup_struct(src_grid) dst_grid%ncoords = count(blend%mask .eq. mask) dst_grid%nz = 1 call variable_interface_setup_struct(dst_grid) src_ncoords = 0 dst_ncoords = 0 ! Allocate memory for local variables if(.not. allocated(blend%var)) & & allocate(blend%var(src_grid%ncoords,src_grid%nz)) ! Loop through local variable do i = 1, blend%ncoords ! Check local variable and proceed accordingly if(blend%mask(i) .eq. spval) then ! Define local variables src_ncoords = src_ncoords + 1 src_grid%lat(src_ncoords) = blend%lat(i) src_grid%lon(src_ncoords) = blend%lon(i) blend%var(src_ncoords,:) = blend%var_blend(i,:) end if ! if(blend%mask(i) .eq. spval) ! Check local variable and proceed accordingly if(blend%mask(i) .eq. mask) then ! Define local variables dst_ncoords = dst_ncoords + 1 dst_grid%lat(dst_ncoords) = blend%lat(i) dst_grid%lon(dst_ncoords) = blend%lon(i) blend%idx(i) = dst_ncoords end if ! if(blend%mask(i) .eq. mask) end do ! do i = 1, blend%ncoords ! Check local variable and proceed accordingly if(is_slint) then ! Define local variables slint%ncoords = dst_ncoords call variable_interface_setup_struct(slint) ! Compute local variables call interpolation_interface_init(src_grid,dst_grid,slint) end if ! if(is_slint) ! Define local variables blend%scoords = src_ncoords ! Deallocate memory for local variables call variable_interface_cleanup_struct(src_grid) call variable_interface_cleanup_struct(dst_grid) !===================================================================== end subroutine grid_blend !======================================================================= ! SUBROUTINE: ! init_mask_merge.f90 ! DESCRIPTION: ! This subroutine initializes the blending mask used to merge two ! identical dimension grid variables. ! INPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable; it is assumed that all ! arrays within the structure and the respective blending ! attributes have been specified before calling this routine. ! OUTPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable containing the merging ! and blending mask regions. !----------------------------------------------------------------------- subroutine init_mask_merge(merge) ! Define variables passed to routine type(merge_struct) :: merge ! Define variables computed within routine real(r_kind) :: mnlat_fg real(r_kind) :: mnlon_fg real(r_kind) :: mxlat_fg real(r_kind) :: mxlon_fg !===================================================================== ! Define local variables mnlat_fg = minval(merge%lat_fg) mnlon_fg = minval(merge%lon_fg) mxlat_fg = maxval(merge%lat_fg) mxlon_fg = maxval(merge%lon_fg) merge%mask = 1.0 where(merge%lat_an .lt. mnlat_fg) merge%mask = -1.0 where(merge%lon_an .lt. mnlon_fg) merge%mask = -1.0 where(merge%lat_an .gt. mxlat_fg) merge%mask = -1.0 where(merge%lon_an .gt. mxlon_fg) merge%mask = -1.0 !===================================================================== end subroutine init_mask_merge !======================================================================= ! SUBROUTINE: ! interpolate.f90 ! DESCRIPTION: ! This subroutine remaps a user specified variable using the user ! specified interpolation remapping scheme bi-linear method. ! INPUT VARIABLES: ! * nlevs; a FORTRAN integer value specifying the total number of ! vertical levels. ! * src_grid; a FORTRAN grid_struct variable containing the ! geographical locations which do not contain missing values ! (e.g., spval) and the associated variable values. ! * dst_grid; a FORTRAN grid_struct variable containing the ! geographical locations of the destination grid. ! OUTPUT VARIABLES: ! * dst_grid; a FORTRAN grid_struct variable containing the ! interpolated variable values within the structure variable ! 'var'. !----------------------------------------------------------------------- subroutine interpolate(nlevs,src_grid,dst_grid) ! Define variables passed to routine integer :: nlevs type(grid_struct) :: src_grid type(grid_struct) :: dst_grid ! Define variables computed within routine type(slint_struct) :: slint ! Define counting variables integer :: i !===================================================================== ! Check local variable and proceed accordingly if(is_slint) then ! Define local variables slint%ncoords = dst_grid%ncoords slint%src_ncoords = src_grid%ncoords call variable_interface_setup_struct(slint) ! Compute local variables call interpolation_interface_init(src_grid,dst_grid,slint) end if ! if(is_slint) ! Loop through local variable do i = 1, nlevs ! Check local variable and proceed accordingly if(is_slint) then ! Compute local variables call interpolation_interface_bilinear(slint,src_grid%var(:,i)) ! Define local variables dst_grid%var(:,i) = slint%var end if ! if(is_slint) end do ! do i = 1, nlevs ! Deallocate memory for local variables call variable_interface_cleanup_struct(slint) !===================================================================== end subroutine interpolate !======================================================================= ! SUBROUTINE: ! interpolate_subregion.f90 ! DESCRIPTION: ! This subroutine interpolates a sub-region (dst_sub_grid) of the ! destination geographical projection (dst_grid). ! INPUT VARIABLES: ! * src_grid; a FORTRAN grid_struct variable containing geographical ! locations and values to remapped to the sub-region grid ! projection. ! * dst_sub_grid; a FORTRAN grid_struct variable containing the ! geographical locations within the destination grid projection ! for remapping of the source geographical projection (src_grid) ! values. ! * dst_grid; a FORTRAN grid_struct variable to contain the source ! grid values remapped within the destination grid sub-region. ! OUTPUT VARIABLES: ! * dst_grid; a FORTRAN grid_struct variable containing the source ! grid values remapped within the destination grid sub-region. !----------------------------------------------------------------------- subroutine interpolate_subregion(src_grid,dst_sub_grid,dst_grid) ! Define variables passed to routine type(grid_struct) :: dst_grid type(grid_struct) :: dst_sub_grid type(grid_struct) :: src_grid ! Define variables computed within routine integer :: dst_idx ! Define counting variables integer :: i, j !===================================================================== ! Compute local variables call interpolate(src_grid%nz,src_grid,dst_sub_grid) ! Loop through local variable do j = 1, dst_grid%nz ! Loop through local variable do i = 1, dst_sub_grid%ncoords ! Define local variables dst_idx = dst_sub_grid%idx(i) dst_grid%var(dst_idx,j) = dst_sub_grid%var(i,j) end do ! do i = 1, dst_sub_grid%ncoords end do ! do j = 1, dst_grid%nz !===================================================================== end subroutine interpolate_subregion !======================================================================= ! SUBROUTINE: ! mask_fill.f90 ! DESCRIPTION: ! This subroutine determines the edges of the masked region (e.g., ! where the local values are greater than 0.0) and fills all values ! within that array interval with the mask value. ! INPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable with the initial mask ! region (e.g., all mask values with a non-zero variable value ! difference are set to 1.0). ! OUTPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable with a mask region that ! has been filled within the respective interval. !----------------------------------------------------------------------- subroutine mask_fill(blend) ! Define variables passed to routine type(blend_struct) :: blend ! Define variables computed within routine real(r_kind), dimension(:,:), allocatable :: grid_mask real(r_kind) :: mxval integer :: mnxidx integer :: mxxidx integer :: mnyidx integer :: mxyidx ! Define counting variables integer :: i, j !===================================================================== ! Allocate memory for local variables if(.not. allocated(grid_mask)) allocate(grid_mask(blend%nx,blend%ny)) ! Define local variables grid_mask = reshape(blend%mask,shape(grid_mask)) ! Loop through local variable do j = 1, blend%ny ! Define local variables mxval = maxval(grid_mask(:,j)) ! Check local variable and proceed accordingly if(mxval .gt. 0.0) then ! Define local variables mnxidx = blend%nx mxxidx = 1 ! Loop through local variable do i = 1, blend%nx ! Check local variable and proceed accordingly if(grid_mask(i,j) .gt. 0.0) then ! Define local variables mnxidx = min(mnxidx,i) mxxidx = max(mxxidx,i) end if ! if(grid_mask(i,j) .gt. 0.0) end do ! do i = 1, blend%nx ! Define local variables grid_mask(mnxidx:mxxidx,j) = 1.0 end if ! if(mxval .gt. 0.0) end do ! do j = 1, blend%ny ! Loop through local variable do i = 1, blend%nx ! Define local variables mxval = maxval(grid_mask(i,:)) ! Check local variable and proceed accordingly if(mxval .gt. 0.0) then ! Define local variables mnyidx = blend%ny mxyidx = 1 ! Loop through local variable do j = 1, blend%ny ! Check local variable and proceed accordingly if(grid_mask(i,j) .gt. 0.0) then ! Define local variables mnyidx = min(mnyidx,j) mxyidx = max(mxyidx,j) end if ! if(grid_mask(i,j) .gt. 0.0) end do ! do j = 1, blend%ny ! Define local variables grid_mask(i,mnyidx:mxyidx) = 1.0 end if ! if(mxval .gt. 0.0) end do ! do i = 1, blend%nx ! Define local variables blend%mask = reshape(grid_mask,shape(blend%mask)) ! Deallocate memory for local variables if(allocated(grid_mask)) deallocate(grid_mask) !===================================================================== end subroutine mask_fill !======================================================================= ! SUBROUTINE: ! mask_relax_boundary.f90 ! DESCRIPTION: ! This subroutine defines the blending (i.e., relaxation) region for ! two variables of identical dimension and identical grid projectio; ! the size of the blending region is specified by the user and ! carried in the FORTRAN blend_struct variable 'npts_blend' ! attribute. ! INPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable with a mask region that ! has been filled within the respective interval and contains the ! attribute 'npts_blend'. ! OUTPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable within a mask region that ! now contains the relaxation region also; the relaxation region ! is specified by the 'spval' attribute while non-mask regions are ! denoted by a value of 0.0 within the mask. !----------------------------------------------------------------------- subroutine mask_relax_boundary(blend) ! Define variables passed to routine type(blend_struct) :: blend ! Define variables computed within routine real(r_kind), dimension(:,:), allocatable :: grid_mask real(r_kind) :: grid_value real(r_kind) :: mxval integer :: mnxidx integer :: mxxidx integer :: mnyidx integer :: mxyidx integer :: mnx integer :: mxx integer :: mny integer :: mxy ! Define counting variables integer :: i, j, k !===================================================================== ! Allocate memory for local variables if(.not. allocated(grid_mask)) allocate(grid_mask(blend%nx,blend%ny)) ! Define local variables grid_mask = reshape(blend%mask,shape(grid_mask)) mnx = imin mxx = imax mny = imin mxy = imax ! Loop through local variable do j = blend%bmny, blend%bmxy ! Loop through local variable do i = blend%bmnx, blend%rmnx ! Define local variables grid_value = (i - blend%bmnx) + 1 grid_mask(i,j) = grid_value end do ! do i = blend%bmnx, blend%rmnx ! Loop through local variable do i = blend%rmxx, blend%bmxx ! Define local variables grid_value = (blend%bmxx - i) + 1 grid_mask(i,j) = grid_value end do ! do i = blend%bmnx, blend%rmnx end do ! do j = 1, blend%ny ! Loop through local variable do i = blend%bmnx, blend%bmxx ! Loop through local variable do j = blend%bmny, blend%rmny ! Define local variables grid_value = (j - blend%bmny) + 1 grid_mask(i,j) = grid_value end do ! do j = blend%bmny, blend%rmny ! Loop through local variable do j = blend%rmxy, blend%bmxy ! Define local variables grid_value = (blend%bmxy - j) + 1 grid_mask(i,j) = grid_value end do ! do j = blend%bmny, blend%rmny end do ! do i = blend%bmnx, blend%rmnx ! Define local variables where(grid_mask .le. 1.0) grid_mask = spval blend%mask = reshape(grid_mask,shape(blend%mask)) ! Deallocate memory for local variables if(allocated(grid_mask)) deallocate(grid_mask) !===================================================================== end subroutine mask_relax_boundary !======================================================================= ! SUBROUTINE: ! mask_relax_merge.f90 ! DESCRIPTION: ! This subroutine defines the blending (i.e., relaxation) region ! surrounding a first-guess grid relative to the analysis grid ! within which it is to be inserted (i.e., merged); the size of the ! blending region is specified by the user and carried in the ! FORTRAN merge_struct variable 'npts_blend' and 'npts_relax' attributes. ! INPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable with a mask region that ! has been filled within the respective interval and contains the ! attributes 'npts_blend' and 'npts_relax'. ! OUTPUT VARIABLES: ! * merge; a FORTRAN merge_struct variable within a mask region that ! now contains the relaxation region also; the relaxation region ! is specified by the 'spval' attribute while non-mask regions are ! denoted by a value of 0.0 within the mask. !----------------------------------------------------------------------- subroutine mask_relax_merge(merge) ! Define variables passed to routine type(merge_struct) :: merge ! Define variables computed within routine type(blend_struct) :: blend real(r_kind), dimension(:,:), allocatable :: grid_mask real(r_kind), dimension(:,:), allocatable :: workgrid ! Define counting variables integer :: i, j, k !===================================================================== ! Allocate memory for local variables if(.not. allocated(grid_mask)) allocate(grid_mask(merge%nx,merge%ny)) if(.not. allocated(workgrid)) allocate(workgrid(merge%nx,merge%ny)) ! Define local variables grid_mask = reshape(merge%mask,shape(grid_mask)) workgrid = grid_mask where(workgrid .lt. 0.0) workgrid = spval blend%nx = merge%nx blend%ny = merge%ny blend%nz = merge%nz call variable_interface_setup_struct(blend) blend%npts_relax = merge%npts_relax blend%npts_blend = merge%npts_blend blend%mask = merge%mask call mask_relax_nest(blend) grid_mask = reshape(blend%mask,(/merge%nx,merge%ny/)) ! Loop through local variable do i = 1, merge%nx ! Check local variable and proceed accordingly if(maxval(workgrid(i,1:blend%mny)) .ne. spval) then ! Define local variables grid_mask(i,1:blend%mny) = spval end if ! if(maxval(workgrid(i,1:blend%mny)) .ne. spval) ! Check local variable and proceed accordingly if(maxval(workgrid(i,blend%mxy:blend%nx)) .ne. spval) then ! Define local variables grid_mask(i,blend%mxy:blend%nx) = spval end if ! if(maxval(workgrid(i,blend%mxy:blend%nx)) .ne. spval) end do ! do i = 1, merge%nx ! Loop through local variable do j = 1, merge%ny ! Check local variable and proceed accordingly if(maxval(workgrid(1:blend%mnx,j)) .ne. spval) then ! Define local variables grid_mask(1:blend%mnx,j) = spval end if ! if(maxval(workgrid(1:blend%mnx,j)) .ne. spval) ! Check local variable and proceed accordingly if(maxval(workgrid(blend%mxx:blend%nx,j)) .ne. spval) then ! Define local variables grid_mask(blend%mxx:blend%nx,j) = spval end if ! if(maxval(workgrid(blend%mxx:blend%nx,j)) .ne. spval) end do ! do j = 1, merge%ny ! Define local variables merge%mask = reshape(grid_mask,shape(merge%mask)) ! Deallocate memory for local variables call variable_interface_cleanup_struct(blend) if(allocated(grid_mask)) deallocate(grid_mask) if(allocated(workgrid)) deallocate(workgrid) !===================================================================== end subroutine mask_relax_merge !======================================================================= ! SUBROUTINE: ! mask_relax_nest.f90 ! DESCRIPTION: ! This subroutine defines the blending (i.e., relaxation) region ! surrounding the nest and it's location within it's respective ! parent domain; the size of the blending region is specified by the ! user and carried in the FORTRAN blend_struct variable 'npts_blend' ! attribute. ! INPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable with a mask region that ! has been filled within the respective interval and contains the ! attribute 'npts_blend'. ! OUTPUT VARIABLES: ! * blend; a FORTRAN blend_struct variable within a mask region that ! now contains the relaxation region also; the relaxation region ! is specified by the 'spval' attribute while non-mask regions are ! denoted by a value of 0.0 within the mask. !----------------------------------------------------------------------- subroutine mask_relax_nest(blend) ! Define variables passed to routine type(blend_struct) :: blend ! Define variables computed within routine real(r_kind), dimension(:,:), allocatable :: grid_mask real(r_kind) :: mxval integer :: mnxidx integer :: mxxidx integer :: mnyidx integer :: mxyidx integer :: mnx integer :: mxx integer :: mny integer :: mxy ! Define counting variables integer :: i, j, k !===================================================================== ! Allocate memory for local variables if(.not. allocated(grid_mask)) allocate(grid_mask(blend%nx,blend%ny)) ! Define local variables grid_mask = reshape(blend%mask,shape(grid_mask)) mnx = imin mxx = imax mny = imin mxy = imax ! Loop through local variable do j = 1, blend%ny ! Define local variables mxval = maxval(grid_mask(:,j)) ! Check local variable and proceed accordingly if(mxval .gt. 0.0) then ! Define local variables mnxidx = blend%nx mxxidx = 1 ! Loop through local variable do i = 1, blend%nx ! Check local variable and proceed accordingly if(grid_mask(i,j) .gt. 0.0) then ! Define local variables mnxidx = min(mnxidx,(i + blend%npts_relax)) mxxidx = max(mxxidx,(i - blend%npts_relax)) end if ! if(grid_mask(i,j) .gt. 0.0) end do ! do i = 1, blend%nx ! Loop through local variable do i = (blend%npts_blend + blend%npts_relax), 1, -1 ! Define local variables mnx = max(1,(mnxidx - i)) mxx = min(blend%nx,(mxxidx + i)) grid_mask(mnx:mnxidx,j) = real(i) grid_mask(mxxidx:mxx,j) = real(i) end do ! do i = (blend%npts_blend + blend%npts_relax), 1, -1 end if ! if(mxval .gt. 0.0) end do ! do j = 1, blend%ny ! Loop through local variable do i = 1, blend%nx ! Define local variables mxval = maxval(grid_mask(i,:)) ! Check local variable and proceed accordingly if(mxval .gt. 0.0) then ! Define local variables mnyidx = blend%ny mxyidx = 1 ! Loop through local variable do j = 1, blend%ny ! Check local variable and proceed accordingly if((grid_mask(i,j) .gt. 0.0)) then ! Define local variables mnyidx = min(mnyidx,(j + blend%npts_relax)) mxyidx = max(mxyidx,(j - blend%npts_relax)) end if ! if((grid_mask(i,j) .gt. 0.0)) end do ! do j = 1, blend%ny ! Loop through local variable do j = (blend%npts_blend + blend%npts_relax), 1, -1 ! Define local variables mny = max(1,(mnyidx - j)) mxy = min(blend%ny,(mxyidx + j)) grid_mask(i,mny:mnyidx) = real(j) grid_mask(i,mxyidx:mxy) = real(j) end do ! do j = (blend%npts_blend + blend%npts_relax), 1, -1 end if ! if(mxval .gt. 0.0) end do ! do i = 1, blend%nx ! Define local variables blend%mnx = mnx blend%mny = mny blend%mxx = mxx blend%mxy = mxy where(grid_mask .le. 1.0) grid_mask = spval blend%mask = reshape(grid_mask,shape(blend%mask)) ! Deallocate memory for local variables if(allocated(grid_mask)) deallocate(grid_mask) !===================================================================== end subroutine mask_relax_nest !======================================================================= ! SUBROUTINE: ! region_blend.f90 ! DESCRIPTION: ! This subroutine blends values to fill a missing data region ! (signified by a value of 'spval') within the input variable grid ! (in_grid) and fills the respective locations (determined via ! interpolation) within the output grid (out_grid). ! INPUT VARIABLES: ! * in_grid; a FORTRAN grid_struct variable containing a region of ! missing data values to be populated via interpolation. ! * out_grid; a FORTRAN grid_struct variable containing the ! geographical locations for the destination grid. ! OUTPUT VARIABLES: ! * out_grid; a FORTRAN grid_struct variable containing variable ! values where the input grid once contained missing data value; ! these values are determined via interpolation. !----------------------------------------------------------------------- subroutine region_blend(in_grid,out_grid) ! Define variables passed to routine type(grid_struct) :: in_grid type(grid_struct) :: out_grid ! Define variables computed within routine real(r_kind) :: mask_relax ! Define counting variables integer :: i, j !===================================================================== ! Loop through local variable do i = 1, out_grid%ncoords ! Check local variable and proceed accordingly if(out_grid%radius(i) .le. tc_ic_radius) then ! Loop through local variable do j = 1, out_grid%nz ! Define local variables out_grid%var(i,j) = in_grid%var(i,j) end do ! do j = 1, out_grid%nz end if ! if(out_grid%radius(i) .le. tc_ic_radius) ! Check local variable and proceed accordingly if((out_grid%radius(i) .gt. tc_ic_radius) .and. & & (out_grid%radius(i) .lt. tc_env_radius)) then ! Compute local variables mask_relax = (in_grid%radius(i) - tc_ic_radius)/(tc_env_radius & & - tc_ic_radius) ! Loop through local variable do j = 1, out_grid%nz ! Compute local variables out_grid%var(i,j) = in_grid%var(i,j)*(1.0 - mask_relax) + & & out_grid%var(i,j)*mask_relax end do ! do j = 1, out_grid%nz end if ! if((out_grid%radius(i) .gt. tc_ic_radius) ! .and. (out_grid%radius(i) .lt. tc_env_radius)) end do ! do i = 1, out_grid%ncoords !===================================================================== end subroutine region_blend !======================================================================= ! SUBROUTINE: ! wnd2d_tc_increment.f90 ! DESCRIPTION: ! This subroutine computes the wave-number spectra for the ! respective variable using the Fast-Fourier Transform (FFT); the ! variable is first recentered relative to the geographical location ! of the TC; the 2-dimensional FFT is computed along each azimuth ! for all radii within the user specified radius of influence; the ! spectral components to be retained by the user are than projected ! back to a geographical map projection and returned via a FORTRAN ! grid_struct variable (dst_grid). ! INPUT VARIABLES: ! * grid; a FORTRAN grid_struct variable containing the analysis ! increment and the corresponding grid-projection attributes. ! * tcv; a FORTRAN tcv_struct variable containing the geographical ! location for the respective TC about which to center the FFT. ! * dst_grid; a FORTRAN grid_struct variable to contain the ! wave-number spectra remapped to the geographical projection of ! the input grid (grid). ! OUTPUT VARIABLES: ! * dst_grid; a FORTRAN grid_struct variable to containing the ! wave-number spectra remapped to the geographical projection of ! the input grid (grid). !----------------------------------------------------------------------- subroutine wnd2d_tc_increment(grid,tcv,dst_grid) ! Define variables passed to routine type(grid_struct) :: dst_grid type(grid_struct) :: grid type(tcv_struct) :: tcv ! Define variables computed within routine type(grid_struct) :: dst_sub_grid type(grid_struct) :: src_grid type(recenter_struct) :: recenter type(wnd2d_struct) :: wnd2d integer :: dst_sub_cnt ! Define counting variables integer :: i, j !===================================================================== ! Define local variables recenter%clon = tcv%lon recenter%clat = tcv%lat recenter%area = wndcmp_area recenter%darea = wndcmp_darea recenter%nz = grid%nz call interpolation_interface_init(recenter) ! Compute local variables call interpolation_interface_bilinear(grid,recenter) ! Define local variables wnd2d%nx = recenter%nx wnd2d%ny = recenter%ny wnd2d%maxradius = maxval(recenter%radius) wnd2d%dradius = wndcmp_dradius wnd2d%dangle = wndcmp_dangle call variable_interface_setup_struct(wnd2d) ! Loop through local variable do j = 1, recenter%nz ! Define local variables wnd2d%var = recenter%var(:,j) ! Compute local variables call math_methods_wnd(wnd2d,recenter,src_grid) ! Define local variables src_grid%var(:,j) = 0.0 ! Loop through local variable do i = 1, min((wndcmp_mxwvn + 1),wnd2d%nh) ! Compute local variables src_grid%var(:,j) = src_grid%var(:,j) + & & reshape(wnd2d%wnvar(i,:,:),shape(src_grid%var(:,j))) end do ! do i = 1, min((wndcmp_mxwvn + 1),wnd2d%nh) end do ! do j = 1, recenter%nz ! Define local variables dst_sub_cnt = count((grid%lat .ge. minval(src_grid%lat)) & & .and. (grid%lat .le. maxval(src_grid%lat)) .and. (grid%lon & & .ge. minval(src_grid%lon)) .and. (grid%lon .le. & & maxval(src_grid%lon))) dst_sub_grid%ncoords = dst_sub_cnt dst_sub_grid%nz = grid%nz call variable_interface_setup_struct(dst_sub_grid) ! Define local variables dst_sub_cnt = 0 ! Loop through local variable do i = 1, grid%ncoords ! Check local variable and proceed accordingly if((grid%lat(i) .ge. minval(src_grid%lat)) .and. (grid%lat(i) .le. & & maxval(src_grid%lat)) .and. (grid%lon(i) .ge. & & minval(src_grid%lon)) .and. (grid%lon(i) .le. & & maxval(src_grid%lon))) then ! Define local variables dst_sub_cnt = dst_sub_cnt + 1 dst_sub_grid%lat(dst_sub_cnt) = grid%lat(i) dst_sub_grid%lon(dst_sub_cnt) = grid%lon(i) dst_sub_grid%idx(dst_sub_cnt) = i end if ! if((grid%lat(i) .ge. minval(src_grid%lat)) ! .and. (grid%lat(i) .le. maxval(src_grid%lat)) ! .and. (grid%lon(i) .ge. minval(src_grid%lon)) ! .and. (grid%lon(i) .le. maxval(src_grid%lon))) end do ! do i = 1, grid%ncoords ! Compute local variables call interpolate_subregion(src_grid,dst_sub_grid,dst_grid) ! Deallocate memory for local variables call variable_interface_cleanup_struct(src_grid) call variable_interface_cleanup_struct(dst_sub_grid) !===================================================================== end subroutine wnd2d_tc_increment !======================================================================= ! SUBROUTINE: ! zero_tc_increment.f90 ! DESCRIPTION: ! This subroutine sets all analysis increment values within the user ! specified inner-core region of the tropical cyclone (TC) to zero. ! INPUT VARIABLES: ! * grid; a FORTRAN grid_struct variable containing the analysis ! increment and the corresponding grid-projection attributes. ! * dst_grid; a FORTRAN grid_struct variable to contain the updated ! analysis increments. ! OUTPUT VARIABLES: ! * dst_grid; a FORTRAN grid_struct variable to containing the ! updated analysis increments. !----------------------------------------------------------------------- subroutine zero_tc_increment(grid,dst_grid) ! Define variables passed to routine type(grid_struct) :: dst_grid type(grid_struct) :: grid ! Define counting variables integer :: i !===================================================================== ! Define local variables dst_grid%var = grid%var ! Loop through local variable do i = 1, dst_grid%nz ! Define local variables where(dst_grid%radius .le. tc_ic_radius) dst_grid%var(:,i) = 0.0 end do ! do i = 1, dst_grid%nz !===================================================================== end subroutine zero_tc_increment !======================================================================= end module analysis_interface