diff --git a/generic3g/specs/FieldSpec.F90 b/generic3g/specs/FieldSpec.F90 index 3bf137f27686..168e1d532df9 100644 --- a/generic3g/specs/FieldSpec.F90 +++ b/generic3g/specs/FieldSpec.F90 @@ -477,18 +477,22 @@ logical function can_connect_to(this, src_spec, rc) class(StateItemSpec), intent(in) :: src_spec integer, optional, intent(out) :: rc - logical :: can_convert_units_ + logical :: can_convert_units + logical :: can_connect_vertical_grid integer :: status select type(src_spec) class is (FieldSpec) - can_convert_units_ = can_connect_units(this%units, src_spec%units, _RC) + can_convert_units = can_connect_units(this%units, src_spec%units, _RC) + can_connect_vertical_grid = this%vertical_grid%can_connect_to(src_spec%vertical_grid, _RC) + can_connect_to = all ([ & can_match(this%geom,src_spec%geom), & + can_connect_vertical_grid, & match(this%vertical_dim_spec,src_spec%vertical_dim_spec), & match(this%ungridded_dims,src_spec%ungridded_dims), & includes(this%attributes, src_spec%attributes), & - can_convert_units_ & + can_convert_units & ]) class default can_connect_to = .false. @@ -636,16 +640,16 @@ subroutine make_extension_safely(this, dst_spec, new_spec, action, rc) _RETURN(_SUCCESS) end if - _ASSERT(allocated(this%vertical_grid), 'Source spec must specify a valid vertical grid.') - if (.not. same_vertical_grid(this%vertical_grid, dst_spec%vertical_grid)) then - _HERE - call this%vertical_grid%get_coordinate_field(v_in_coord, v_in_coupler, & - 'ignore', this%geom, this%typekind, this%units, _RC) - call this%vertical_grid%get_coordinate_field(v_out_coord, v_out_coupler, & - 'ignore', dst_spec%geom, dst_spec%typekind, dst_spec%units, _RC) - action = VerticalRegridAction(v_in_coord, v_out_coupler, v_out_coord, v_out_coupler, VERTICAL_REGRID_LINEAR) - _RETURN(_SUCCESS) - end if + _ASSERT(allocated(this%vertical_grid), 'Source spec must specify a valid vertical grid.') + if (.not. same_vertical_grid(this%vertical_grid, dst_spec%vertical_grid)) then + _HERE + call this%vertical_grid%get_coordinate_field(v_in_coord, v_in_coupler, & + 'ignore', this%geom, this%typekind, this%units, _RC) + call this%vertical_grid%get_coordinate_field(v_out_coord, v_out_coupler, & + 'ignore', dst_spec%geom, dst_spec%typekind, dst_spec%units, _RC) + action = VerticalRegridAction(v_in_coord, v_out_coupler, v_out_coord, v_out_coupler, VERTICAL_REGRID_LINEAR) + _RETURN(_SUCCESS) + end if !# if (.not. same_freq_spec(this%freq_spec, dst_spec%freq_spec)) then !# action = VerticalRegridAction(this%freq_spec, dst_spec%freq_spec @@ -720,6 +724,7 @@ logical function can_match_geom(a, b) result(can_match) end function can_match_geom + logical function match_geom(a, b) result(match) type(ESMF_Geom), allocatable, intent(in) :: a, b diff --git a/generic3g/vertical/BasicVerticalGrid.F90 b/generic3g/vertical/BasicVerticalGrid.F90 index b0e6d9eb91fd..b8eb6d5410f4 100644 --- a/generic3g/vertical/BasicVerticalGrid.F90 +++ b/generic3g/vertical/BasicVerticalGrid.F90 @@ -17,6 +17,7 @@ module mapl3g_BasicVerticalGrid contains procedure :: get_num_levels procedure :: get_coordinate_field + procedure :: can_connect_to end type BasicVerticalGrid interface operator(==) @@ -31,6 +32,15 @@ module mapl3g_BasicVerticalGrid module procedure new_BasicVerticalGrid end interface BasicVerticalGrid + interface + module function can_connect_to(this, src, rc) + logical :: can_connect_to + class(BasicVerticalGrid), intent(in) :: this + class(VerticalGrid), intent(in) :: src + integer, optional, intent(out) :: rc + end function + end interface + contains function new_BasicVerticalGrid(num_levels) result(vertical_grid) @@ -69,4 +79,5 @@ elemental logical function not_equal_to(a, b) not_equal_to = .not. (a == b) end function not_equal_to + end module mapl3g_BasicVerticalGrid diff --git a/generic3g/vertical/BasicVerticalGrid/can_connect_to.F90 b/generic3g/vertical/BasicVerticalGrid/can_connect_to.F90 new file mode 100644 index 000000000000..3cc14928c4fb --- /dev/null +++ b/generic3g/vertical/BasicVerticalGrid/can_connect_to.F90 @@ -0,0 +1,27 @@ +#include "MAPL_ErrLog.h" +submodule (mapl3g_BasicVerticalGrid) can_connect_to_smod + use mapl3g_MirrorVerticalGrid + use mapl3g_ModelVerticalGrid + +contains + + logical module function can_connect_to(this, src, rc) + class(BasicVerticalGrid), intent(in) :: this + class(VerticalGrid), intent(in) :: src + integer, optional, intent(out) :: rc + + select type(src) + type is (BasicVerticalGrid) + can_connect_to = (this%get_num_levels() == src%get_num_levels()) + type is (MirrorVerticalGrid) + can_connect_to = .true. + type is (ModelVerticalGrid) + can_connect_to = (this%get_num_levels() == src%get_num_levels()) + class default + _FAIL('BasicVerticalGrid can only connect to src BasicVerticalGrid, MirrorVerticalGrid, or ModelVerticalGrid instances.') + end select + + _RETURN(_SUCCESS) + end function can_connect_to + +end submodule diff --git a/generic3g/vertical/CMakeLists.txt b/generic3g/vertical/CMakeLists.txt index ad3eebcd41a2..1d9d4fa43656 100644 --- a/generic3g/vertical/CMakeLists.txt +++ b/generic3g/vertical/CMakeLists.txt @@ -5,4 +5,17 @@ target_sources(MAPL.generic3g PRIVATE MirrorVerticalGrid.F90 FixedLevelsVerticalGrid.F90 ModelVerticalGrid.F90 - ) +) + +esma_add_fortran_submodules( + TARGET MAPL.generic3g + SUBDIRECTORY BasicVerticalGrid + SOURCES can_connect_to.F90 +) + +esma_add_fortran_submodules( + TARGET MAPL.generic3g + SUBDIRECTORY ModelVerticalGrid + SOURCES can_connect_to.F90 +) + diff --git a/generic3g/vertical/FixedLevelsVerticalGrid.F90 b/generic3g/vertical/FixedLevelsVerticalGrid.F90 index 4ac4088198df..08bd7b24fd47 100644 --- a/generic3g/vertical/FixedLevelsVerticalGrid.F90 +++ b/generic3g/vertical/FixedLevelsVerticalGrid.F90 @@ -22,6 +22,7 @@ module mapl3g_FixedLevelsVerticalGrid contains procedure :: get_num_levels procedure :: get_coordinate_field + procedure :: can_connect_to end type FixedLevelsVerticalGrid interface FixedLevelsVerticalGrid @@ -58,5 +59,14 @@ subroutine get_coordinate_field(this, field, coupler, standard_name, geom, typek _FAIL('not implemented') end subroutine get_coordinate_field + logical function can_connect_to(this, src, rc) + class(FixedLevelsVerticalGrid), intent(in) :: this + class(VerticalGrid), intent(in) :: src + integer, optional, intent(out) :: rc + + _FAIL('not implemented') + + end function can_connect_to + end module mapl3g_FixedLevelsVerticalGrid diff --git a/generic3g/vertical/MirrorVerticalGrid.F90 b/generic3g/vertical/MirrorVerticalGrid.F90 index 0986d7a856de..15feb6166a10 100644 --- a/generic3g/vertical/MirrorVerticalGrid.F90 +++ b/generic3g/vertical/MirrorVerticalGrid.F90 @@ -21,6 +21,7 @@ module mapl3g_MirrorVerticalGrid contains procedure :: get_num_levels procedure :: get_coordinate_field + procedure :: can_connect_to end type MirrorVerticalGrid interface MirrorVerticalGrid @@ -52,4 +53,13 @@ subroutine get_coordinate_field(this, field, coupler, standard_name, geom, typek _FAIL('MirrorVerticalGrid should have been replaced before this procedure was called.') end subroutine get_coordinate_field + logical function can_connect_to(this, src, rc) + class(MirrorVerticalGrid), intent(in) :: this + class(VerticalGrid), intent(in) :: src + integer, optional, intent(out) :: rc + + can_connect_to = .false. + _RETURN(_SUCCESS) + end function + end module mapl3g_MirrorVerticalGrid diff --git a/generic3g/vertical/ModelVerticalGrid.F90 b/generic3g/vertical/ModelVerticalGrid.F90 index d65f9fc9e39b..080fdffc08a5 100644 --- a/generic3g/vertical/ModelVerticalGrid.F90 +++ b/generic3g/vertical/ModelVerticalGrid.F90 @@ -35,6 +35,7 @@ module mapl3g_ModelVerticalGrid contains procedure :: get_num_levels procedure :: get_coordinate_field + procedure :: can_connect_to ! subclass-specific methods procedure :: add_variant @@ -47,6 +48,14 @@ module mapl3g_ModelVerticalGrid procedure new_ModelVerticalGrid_basic end interface ModelVerticalGrid + interface + module function can_connect_to(this, src, rc) + logical :: can_connect_to + class(ModelVerticalGrid), intent(in) :: this + class(VerticalGrid), intent(in) :: src + integer, optional, intent(out) :: rc + end function + end interface ! TODO: ! - Ensure that there really is a vertical dimension @@ -180,4 +189,6 @@ subroutine get_coordinate_field(this, field, coupler, standard_name, geom, typek end subroutine get_coordinate_field + + end module mapl3g_ModelVerticalGrid diff --git a/generic3g/vertical/ModelVerticalGrid/can_connect_to.F90 b/generic3g/vertical/ModelVerticalGrid/can_connect_to.F90 new file mode 100644 index 000000000000..595c2f0f7397 --- /dev/null +++ b/generic3g/vertical/ModelVerticalGrid/can_connect_to.F90 @@ -0,0 +1,36 @@ +#include "MAPL_ErrLog.h" +submodule (mapl3g_ModelVerticalGrid) can_connect_to_smod + use mapl3g_BasicVerticalGrid + use mapl3g_MirrorVerticalGrid + +contains + + logical module function can_connect_to(this, src, rc) + use mapl3g_MirrorVerticalGrid, only: MirrorVerticalGrid + use mapl3g_BasicVerticalGrid, only: BasicVerticalGrid + class(ModelVerticalGrid), intent(in) :: this + class(VerticalGrid), intent(in) :: src + integer, optional, intent(out) :: rc + + integer :: status + + if (this%same_id(src)) then + can_connect_to = .true. + _RETURN(_SUCCESS) + end if + + select type (src) + type is (MirrorVerticalGrid) + can_connect_to = .true. + _RETURN(_SUCCESS) + type is (BasicVerticalGrid) + can_connect_to = (this%get_num_levels() == src%get_num_levels()) + _RETURN(_SUCCESS) + class default + _FAIL('unsupported subclass of VerticalGrid') + end select + + _RETURN(_SUCCESS) + end function can_connect_to + +end submodule diff --git a/generic3g/vertical/VerticalGrid.F90 b/generic3g/vertical/VerticalGrid.F90 index 1c8e1fd2cfe3..2efa7ee4554f 100644 --- a/generic3g/vertical/VerticalGrid.F90 +++ b/generic3g/vertical/VerticalGrid.F90 @@ -13,6 +13,7 @@ module mapl3g_VerticalGrid contains procedure(I_get_num_levels), deferred :: get_num_levels procedure(I_get_coordinate_field), deferred :: get_coordinate_field + procedure(I_can_connect_to), deferred :: can_connect_to procedure :: set_id @@ -43,6 +44,13 @@ subroutine I_get_coordinate_field(this, field, coupler, standard_name, geom, typ character(*), intent(in) :: units integer, optional, intent(out) :: rc end subroutine I_get_coordinate_field + + logical function I_can_connect_to(this, src, rc) result(can_connect_to) + import VerticalGrid + class(VerticalGrid), intent(in) :: this + class(VerticalGrid), intent(in) :: src + integer, optional, intent(out) :: rc + end function I_can_connect_to end interface