VerticalRegridAction.F90 Source File


This file depends on

sourcefile~~verticalregridaction.f90~~EfferentGraph sourcefile~verticalregridaction.f90 VerticalRegridAction.F90 sourcefile~componentdriver.f90 ComponentDriver.F90 sourcefile~verticalregridaction.f90->sourcefile~componentdriver.f90 sourcefile~couplerphases.f90 CouplerPhases.F90 sourcefile~verticalregridaction.f90->sourcefile~couplerphases.f90 sourcefile~csr_sparsematrix.f90 CSR_SparseMatrix.F90 sourcefile~verticalregridaction.f90->sourcefile~csr_sparsematrix.f90 sourcefile~errorhandling.f90 ErrorHandling.F90 sourcefile~verticalregridaction.f90->sourcefile~errorhandling.f90 sourcefile~extensionaction.f90 ExtensionAction.F90 sourcefile~verticalregridaction.f90->sourcefile~extensionaction.f90 sourcefile~fieldcondensedarray.f90 FieldCondensedArray.F90 sourcefile~verticalregridaction.f90->sourcefile~fieldcondensedarray.f90 sourcefile~verticallinearmap.f90 VerticalLinearMap.F90 sourcefile~verticalregridaction.f90->sourcefile~verticallinearmap.f90 sourcefile~verticalregridmethod.f90 VerticalRegridMethod.F90 sourcefile~verticalregridaction.f90->sourcefile~verticalregridmethod.f90 sourcefile~componentdriver.f90->sourcefile~errorhandling.f90 sourcefile~maplshared.f90 MaplShared.F90 sourcefile~componentdriver.f90->sourcefile~maplshared.f90 sourcefile~multistate.f90 MultiState.F90 sourcefile~componentdriver.f90->sourcefile~multistate.f90 sourcefile~keywordenforcer.f90 KeywordEnforcer.F90 sourcefile~csr_sparsematrix.f90->sourcefile~keywordenforcer.f90 sourcefile~mapl_throw.f90 MAPL_Throw.F90 sourcefile~errorhandling.f90->sourcefile~mapl_throw.f90 sourcefile~extensionaction.f90->sourcefile~errorhandling.f90 sourcefile~fieldcondensedarray_private.f90 FieldCondensedArray_private.F90 sourcefile~fieldcondensedarray.f90->sourcefile~fieldcondensedarray_private.f90 sourcefile~fieldget.f90 FieldGet.F90 sourcefile~fieldcondensedarray.f90->sourcefile~fieldget.f90 sourcefile~fieldpointerutilities.f90 FieldPointerUtilities.F90 sourcefile~fieldcondensedarray.f90->sourcefile~fieldpointerutilities.f90 sourcefile~mapl_exceptionhandling.f90 MAPL_ExceptionHandling.F90 sourcefile~fieldcondensedarray.f90->sourcefile~mapl_exceptionhandling.f90 sourcefile~verticalstaggerloc.f90 VerticalStaggerLoc.F90 sourcefile~fieldcondensedarray.f90->sourcefile~verticalstaggerloc.f90 sourcefile~verticallinearmap.f90->sourcefile~csr_sparsematrix.f90 sourcefile~verticallinearmap.f90->sourcefile~errorhandling.f90

Files dependent on this one

sourcefile~~verticalregridaction.f90~~AfferentGraph sourcefile~verticalregridaction.f90 VerticalRegridAction.F90 sourcefile~couplermetacomponent.f90 CouplerMetaComponent.F90 sourcefile~couplermetacomponent.f90->sourcefile~verticalregridaction.f90 sourcefile~genericcoupler.f90 GenericCoupler.F90 sourcefile~genericcoupler.f90->sourcefile~verticalregridaction.f90 sourcefile~genericcoupler.f90->sourcefile~couplermetacomponent.f90 sourcefile~verticalgridaspect.f90 VerticalGridAspect.F90 sourcefile~verticalgridaspect.f90->sourcefile~verticalregridaction.f90 sourcefile~aspectcollection.f90 AspectCollection.F90 sourcefile~aspectcollection.f90->sourcefile~verticalgridaspect.f90 sourcefile~fieldspec.f90 FieldSpec.F90 sourcefile~fieldspec.f90->sourcefile~verticalgridaspect.f90 sourcefile~stateitemextension.f90 StateItemExtension.F90 sourcefile~stateitemextension.f90->sourcefile~genericcoupler.f90 sourcefile~variablespec.f90 VariableSpec.F90 sourcefile~variablespec.f90->sourcefile~verticalgridaspect.f90

Source Code

#include "MAPL_Generic.h"

module mapl3g_VerticalRegridAction

   use mapl_ErrorHandling
   use mapl3g_ExtensionAction
   use mapl3g_ComponentDriver
   use mapl3g_CouplerPhases, only: GENERIC_COUPLER_UPDATE
   use mapl3g_VerticalRegridMethod
   use mapl3g_VerticalLinearMap, only: compute_linear_map
   use mapl3g_CSR_SparseMatrix, only: SparseMatrix_sp => CSR_SparseMatrix_sp, matmul
   use mapl3g_FieldCondensedArray, only: assign_fptr_condensed_array
   use esmf

   implicit none
   private

   public :: VerticalRegridAction
   public :: VERTICAL_REGRID_UNKNOWN
   public :: VERTICAL_REGRID_LINEAR
   public :: VERTICAL_REGRID_CONSERVATIVE
   public :: operator(==), operator(/=)

   type, extends(ExtensionAction) :: VerticalRegridAction
      type(ESMF_Field) :: v_in_coord, v_out_coord
      type(SparseMatrix_sp), allocatable :: matrix(:)
      class(ComponentDriver), pointer :: v_in_coupler => null()
      class(ComponentDriver), pointer :: v_out_coupler => null()
      type(VerticalRegridMethod) :: method = VERTICAL_REGRID_UNKNOWN
   contains
      procedure :: initialize
      procedure :: update
      procedure :: write_formatted
      generic :: write(formatted) => write_formatted
   end type VerticalRegridAction

   interface VerticalRegridAction
      procedure :: new_VerticalRegridAction
   end interface VerticalRegridAction

contains

   function new_VerticalRegridAction(v_in_coord, v_in_coupler, v_out_coord, v_out_coupler, method) result(action)
      type(VerticalRegridAction) :: action
      type(ESMF_Field), intent(in) :: v_in_coord
      class(ComponentDriver), pointer, intent(in) :: v_in_coupler
      type(ESMF_Field), intent(in) :: v_out_coord
      class(ComponentDriver), pointer, intent(in) :: v_out_coupler
      type(VerticalRegridMethod), optional, intent(in) :: method

      action%v_in_coord = v_in_coord
      action%v_out_coord = v_out_coord

      action%v_in_coupler => v_in_coupler
      action%v_out_coupler => v_out_coupler

      if (present(method)) then
         action%method = method
      end if
   end function new_VerticalRegridAction

   subroutine initialize(this, importState, exportState, clock, rc)
      class(VerticalRegridAction), intent(inout) :: this
      type(ESMF_State) :: importState
      type(ESMF_State) :: exportState
      type(ESMF_Clock) :: clock
      integer, optional, intent(out) :: rc

      _ASSERT(this%method == VERTICAL_REGRID_LINEAR, "regrid method can only be linear")

      _RETURN(_SUCCESS)
      _UNUSED_DUMMY(importState)
      _UNUSED_DUMMY(exportState)
      _UNUSED_DUMMY(clock)
   end subroutine initialize

   subroutine update(this, importState, exportState, clock, rc)
      class(VerticalRegridAction), intent(inout) :: this
      type(ESMF_State) :: importState
      type(ESMF_State) :: exportState
      type(ESMF_Clock) :: clock
      integer, optional, intent(out) :: rc

      type(ESMF_Field) :: f_in, f_out
      real(ESMF_KIND_R4), pointer :: x_in(:,:,:), x_out(:,:,:)
      integer :: shape_in(3), shape_out(3), n_horz, n_ungridded
      integer :: horz, ungrd, status

      ! if (associated(this%v_in_coupler)) then
      !    call this%v_in_coupler%run(phase_idx=GENERIC_COUPLER_UPDATE, _RC)
      ! end if

      ! if (associated(this%v_out_coupler)) then
      !    call this%v_out_coupler%run(phase_idx=GENERIC_COUPLER_UPDATE, _RC)
      ! end if

      call compute_interpolation_matrix_(this%v_in_coord, this%v_out_coord, this%matrix, _RC)

      call ESMF_StateGet(importState, itemName='import[1]', field=f_in, _RC)
      call assign_fptr_condensed_array(f_in, x_in, _RC)
      shape_in = shape(x_in)
      n_horz = shape_in(1)
      n_ungridded = shape_in(3)

      call ESMF_StateGet(exportState, itemName='export[1]', field=f_out, _RC)
      call assign_fptr_condensed_array(f_out, x_out, _RC)
      shape_out = shape(x_out)

      _ASSERT((shape_in(1) == shape_out(1)), "horz dims are expected to be equal")
      _ASSERT((shape_in(3) == shape_out(3)), "ungridded dims are expected to be equal")

      do concurrent (horz=1:n_horz, ungrd=1:n_ungridded)
         x_out(horz, :, ungrd) = matmul(this%matrix(horz), x_in(horz, :, ungrd))
      end do

      _RETURN(_SUCCESS)
      _UNUSED_DUMMY(clock)
   end subroutine update

   subroutine write_formatted(this, unit, iotype, v_list, iostat, iomsg)
      class(VerticalRegridAction), intent(in) :: this
      integer, intent(in) :: unit
      character(*), intent(in) :: iotype
      integer, intent(in) :: v_list(:)
      integer, intent(out) :: iostat
      character(*), intent(inout) :: iomsg

      real(ESMF_KIND_R4), pointer :: v_in(:), v_out(:)
      integer :: rc, status

      call ESMF_FieldGet(this%v_in_coord, fArrayPtr=v_in, _RC)
      call ESMF_FieldGet(this%v_out_coord, fArrayPtr=v_out, _RC)

      write(unit, "(a, a)", iostat=iostat, iomsg=iomsg) "VerticalRegridAction(", new_line("a")
      if (iostat /= 0) return
      write(unit, "(4x, a, l1, a, 4x, a, l1, a)", iostat=iostat, iomsg=iomsg) &
           "v_in_coupler: ", associated(this%v_in_coupler), new_line("a"), &
           "v_out_coupler: ", associated(this%v_out_coupler), new_line("a")
      if (iostat /= 0) return
      write(unit, "(4x, a, *(g0, 1x))", iostat=iostat, iomsg=iomsg) "v_in_coord: ", v_in
      if (iostat /= 0) return
      write(unit, "(a)", iostat=iostat, iomsg=iomsg) new_line("a")
      if (iostat /= 0) return
      write(unit, "(4x, a, *(g0, 1x))", iostat=iostat, iomsg=iomsg) "v_out_coord: ", v_out
      if (iostat /= 0) return
      write(unit, "(a, 1x, a)", iostat=iostat, iomsg=iomsg) new_line("a"), ")"

      _UNUSED_DUMMY(iotype)
      _UNUSED_DUMMY(v_list)
   end subroutine write_formatted

   subroutine compute_interpolation_matrix_(v_in_coord, v_out_coord, matrix, rc)
      type(ESMF_Field), intent(inout) :: v_in_coord
      type(ESMF_Field), intent(inout) :: v_out_coord
      type(SparseMatrix_sp), allocatable, intent(out) :: matrix(:)
      integer, optional, intent(out) :: rc

      real(ESMF_KIND_R4), pointer :: v_in(:, :, :), v_out(:, :, :)
      integer :: shape_in(3), shape_out(3), n_horz, n_ungridded
      integer :: horz, ungrd, status

      call assign_fptr_condensed_array(v_in_coord, v_in, _RC)
      shape_in = shape(v_in)
      n_horz = shape_in(1)
      n_ungridded = shape_in(3)

      call assign_fptr_condensed_array(v_out_coord, v_out, _RC)
      shape_out = shape(v_out)
      _ASSERT((shape_in(1) == shape_out(1)), "horz dims are expected to be equal")
      _ASSERT((shape_in(3) == shape_out(3)), "ungridded dims are expected to be equal")

      allocate(matrix(n_horz))

      ! TODO: Convert to a `do concurrent` loop
      do horz = 1, n_horz
         do ungrd = 1, n_ungridded
            associate(src => v_in(horz, :, ungrd), dst => v_out(horz, :, ungrd))
              call compute_linear_map(src, dst, matrix(horz), _RC)
            end associate
         end do
      end do

      _RETURN(_SUCCESS)
   end subroutine compute_interpolation_matrix_

end module mapl3g_VerticalRegridAction