diff --git a/CMakeLists.txt b/CMakeLists.txt index 81c4001bedc5..c5b75da2c0ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -212,6 +212,7 @@ add_subdirectory (generic) add_subdirectory (generic3g) add_subdirectory (field) add_subdirectory (field_bundle) +add_subdirectory (state) add_subdirectory (oomph) # temporary - will rename to generic when done add_subdirectory (shared) add_subdirectory (include) diff --git a/generic3g/CMakeLists.txt b/generic3g/CMakeLists.txt index 003d524a2cc8..b3d7adc2ebdf 100644 --- a/generic3g/CMakeLists.txt +++ b/generic3g/CMakeLists.txt @@ -55,7 +55,7 @@ endif () esma_add_library(${this} SRCS ${srcs} - DEPENDENCIES MAPL.regridder_mgr MAPL.geom_mgr MAPL.GeomIO MAPL.esmf_utils MAPL.field MAPL.shared MAPL.profiler MAPL.base MAPL.hconfig_utils + DEPENDENCIES MAPL.regridder_mgr MAPL.geom_mgr MAPL.GeomIO MAPL.esmf_utils MAPL.field MAPL.state MAPL.shared MAPL.profiler MAPL.base MAPL.hconfig_utils ESMF::ESMF NetCDF::NetCDF_Fortran udunits2f PFLOGGER::pflogger GFTL_SHARED::gftl-shared-v2 GFTL::gftl-v2 TYPE SHARED ) diff --git a/generic3g/RestartHandler.F90 b/generic3g/RestartHandler.F90 index 62c75b4ce0e7..d5c2c91fa709 100644 --- a/generic3g/RestartHandler.F90 +++ b/generic3g/RestartHandler.F90 @@ -8,6 +8,7 @@ module mapl3g_RestartHandler use mapl_ErrorHandling, only: MAPL_Verify, MAPL_Return, MAPL_Assert use mapl3g_geomio, only: bundle_to_metadata, GeomPFIO, make_geom_pfio, get_mapl_geom use mapl3g_SharedIO, only: esmf_to_pfio_type + use mapl3g_StateGet, only: MAPL_StateGet use pFIO, only: PFIO_READ, FileMetaData, NetCDF4_FileFormatter use pFIO, only: i_Clients, o_Clients use pFlogger, only: logging, logger @@ -70,7 +71,7 @@ subroutine write(this, state_type, state, rc) ! TODO: the file_name should come from OuterMetaComponents's hconfig file_name = trim(this%gc_name) // "_" // trim(state_type) // "_checkpoint.nc4" call this%lgr%info("Writing checkpoint: %a", trim(file_name)) - out_bundle = get_bundle_from_state_(state, _RC) + out_bundle = MAPL_StateGet(state, _RC) call this%write_bundle_(out_bundle, file_name, rc) end if @@ -106,39 +107,6 @@ subroutine read(this, state_type, state, rc) _RETURN(_SUCCESS) end subroutine read - type(ESMF_FieldBundle) function get_bundle_from_state_(state, rc) result(bundle) - ! Arguments - type(ESMF_State), intent(in) :: state - integer, optional, intent(out) :: rc - - ! Locals - character(len=ESMF_MAXSTR), allocatable :: item_name(:) - type (ESMF_StateItem_Flag), allocatable :: item_type(:) - type(ESMF_Field) :: field - type(ESMF_FieldStatus_Flag) :: field_status - integer :: item_count, idx, status - - ! bundle to pack fields in - bundle = ESMF_FieldBundleCreate(_RC) - call ESMF_StateGet(state, itemCount=item_count, _RC) - allocate(item_name(item_count), _STAT) - allocate(item_type(item_count), _STAT) - call ESMF_StateGet(state, itemNameList=item_name, itemTypeList=item_type, _RC) - do idx = 1, item_count - if (item_type(idx) /= ESMF_STATEITEM_FIELD) then - _FAIL("FieldBundle has not been implemented yet") - end if - call ESMF_StateGet(state, item_name(idx), field, _RC) - call ESMF_FieldGet(field, status=field_status, _RC) - if (field_status == ESMF_FIELDSTATUS_COMPLETE) then - call ESMF_FieldBundleAdd(bundle, [field], _RC) - end if - end do - deallocate(item_name, item_type, _STAT) - - _RETURN(_SUCCESS) - end function get_bundle_from_state_ - subroutine write_bundle_(this, bundle, file_name, rc) ! Arguments class(RestartHandler), intent(in) :: this diff --git a/generic3g/tests/Test_Scenarios.pf b/generic3g/tests/Test_Scenarios.pf index efb19aeff945..a40f876aefed 100644 --- a/generic3g/tests/Test_Scenarios.pf +++ b/generic3g/tests/Test_Scenarios.pf @@ -100,7 +100,7 @@ contains params = [params, add_params('field status', check_field_status)] params = [params, add_params('field typekind', check_field_typekind)] params = [params, add_params('field value', check_field_value)] - params = [params, add_params('field k_values', check_field_k_values)] + params = [params, add_params('field vertical_profile', check_field_vertical_profile)] params = [params, add_params('field exists', check_field_rank)] ! Service oriented tests @@ -515,14 +515,14 @@ contains rc = 0 end subroutine check_field_value - subroutine check_field_k_values(expectations, state, short_name, description, rc) + subroutine check_field_vertical_profile(expectations, state, short_name, description, rc) type(ESMF_HConfig), intent(in) :: expectations type(ESMF_State), intent(inout) :: state character(*), intent(in) :: short_name character(*), intent(in) :: description integer, intent(out) :: rc - real, allocatable :: expected_k_values(:) + real, allocatable :: expected_vertical_profile(:) integer :: rank type(ESMF_TypeKind_Flag) :: typekind integer :: status @@ -539,12 +539,12 @@ contains return end if - if (.not. ESMF_HConfigIsDefined(expectations,keyString='k_values')) then + if (.not. ESMF_HConfigIsDefined(expectations,keyString='vertical_profile')) then rc = 0 return end if - expected_k_values = ESMF_HConfigAsR4Seq(expectations,keyString='k_values',_RC) + expected_vertical_profile = ESMF_HConfigAsR4Seq(expectations,keyString='vertical_profile',_RC) call ESMF_StateGet(state, short_name, field, _RC) call ESMF_FieldGet(field, typekind=typekind, rank=rank, rc=status) @@ -559,7 +559,7 @@ contains shape3 = shape(x3) do i = 1, shape3(1) do j = 1, shape3(2) - @assert_that("value of "//short_name, x3(i, j, :), is(equal_to(expected_k_values))) + @assert_that("value of "//short_name, x3(i, j, :), is(equal_to(expected_vertical_profile))) end do end do case(4) @@ -568,7 +568,7 @@ contains do i = 1, shape4(1) do j = 1, shape4(2) do l = 1, shape4(4) - @assert_that("value of "//short_name, x4(i, j, :, l), is(equal_to(expected_k_values))) + @assert_that("value of "//short_name, x4(i, j, :, l), is(equal_to(expected_vertical_profile))) end do end do end do @@ -585,7 +585,7 @@ contains shape3 = shape(x3) do i = 1, shape3(1) do j = 1, shape3(2) - @assert_that("value of "//short_name, x3(i, j, :), is(equal_to(expected_k_values))) + @assert_that("value of "//short_name, x3(i, j, :), is(equal_to(expected_vertical_profile))) end do end do case(4) @@ -594,7 +594,7 @@ contains do i = 1, shape4(1) do j = 1, shape4(2) do l = 1, shape4(4) - @assert_that("value of "//short_name, x4(i, j, :, l), is(equal_to(expected_k_values))) + @assert_that("value of "//short_name, x4(i, j, :, l), is(equal_to(expected_vertical_profile))) end do end do end do @@ -607,7 +607,7 @@ contains end if rc = 0 - end subroutine check_field_k_values + end subroutine check_field_vertical_profile subroutine check_field_rank(expectations, state, short_name, description, rc) type(ESMF_HConfig), intent(in) :: expectations diff --git a/generic3g/tests/scenarios/vertical_regridding_3/expectations.yaml b/generic3g/tests/scenarios/vertical_regridding_3/expectations.yaml index 90dd51b960dc..40e3d96b7918 100644 --- a/generic3g/tests/scenarios/vertical_regridding_3/expectations.yaml +++ b/generic3g/tests/scenarios/vertical_regridding_3/expectations.yaml @@ -6,12 +6,12 @@ - component: DYN export: PL: {status: complete} - T_DYN: {status: complete, typekind: R4, rank: 3, k_values: [40., 20., 10., 5.]} + T_DYN: {status: complete, typekind: R4, rank: 3, vertical_profile: [40., 20., 10., 5.]} - component: PHYS import: - T_PHYS: {status: complete, typekind: R4, rank: 3, k_values: [18., 6.]} + T_PHYS: {status: complete, typekind: R4, rank: 3, vertical_profile: [18., 6.]} - component: C import: - I_C: {status: complete, typekind: R4, rank: 3, k_values: [40., 20., 10.]} + I_C: {status: complete, typekind: R4, rank: 3, vertical_profile: [40., 20., 10.]} diff --git a/gridcomps/configurable/CMakeLists.txt b/gridcomps/configurable/CMakeLists.txt index 833c5b521392..ac3f2e82332d 100644 --- a/gridcomps/configurable/CMakeLists.txt +++ b/gridcomps/configurable/CMakeLists.txt @@ -2,5 +2,5 @@ esma_set_this (OVERRIDE configurable_gridcomp) esma_add_library(${this} SRCS ConfigurableGridComp.F90 - DEPENDENCIES MAPL.generic3g + DEPENDENCIES MAPL.generic3g MAPL TYPE SHARED) diff --git a/gridcomps/configurable/ConfigurableGridComp.F90 b/gridcomps/configurable/ConfigurableGridComp.F90 index 479ad108804a..0718bcfe4833 100644 --- a/gridcomps/configurable/ConfigurableGridComp.F90 +++ b/gridcomps/configurable/ConfigurableGridComp.F90 @@ -1,9 +1,11 @@ #include "MAPL_Generic.h" -module ConfigurableGridComp +module mapl3g_ConfigurableGridComp use mapl_ErrorHandling use mapl3g_Generic, only: MAPL_GridCompSetEntryPoint, MAPL_RunChildren + use mapl3g_Generic, only: MAPL_GridCompGet + use mapl, only: MAPL_GetPointer use esmf implicit none @@ -11,6 +13,11 @@ module ConfigurableGridComp public :: setServices + character(*), parameter :: MAPL_SECTION = "mapl" + character(*), parameter :: COMPONENT_STATES_SECTION = "states" + character(*), parameter :: COMPONENT_EXPORT_STATE_SECTION = "export" + character(*), parameter :: KEY_DEFAULT_VERT_PROFILE = "default_vertical_profile" + contains subroutine setServices(gridcomp, rc) @@ -32,12 +39,47 @@ subroutine init(gridcomp, importState, exportState, clock, rc) type(ESMF_Clock) :: clock integer, intent(out) :: rc - integer :: status + character(:), allocatable :: field_name + type(ESMF_HConfig) :: hconfig, mapl_cfg, states_cfg, export_cfg, field_cfg + logical :: has_export_section, has_default_vert_profile + real(kind=ESMF_KIND_R4), allocatable :: default_vert_profile(:) + real(kind=ESMF_KIND_R4), pointer :: ptr3d(:, :, :) + integer :: ii, jj, shape_(3), status + + type(ESMF_HConfigIter) :: iter, e, b + + call MAPL_GridCompGet(gridcomp, hconfig=hconfig, _RC) + ! ASSUME: mapl and states sections always exist + mapl_cfg = ESMF_HConfigCreateAt(hconfig, keyString=MAPL_SECTION, _RC) + states_cfg = ESMF_HConfigCreateAt(mapl_cfg, keyString=COMPONENT_STATES_SECTION, _RC) + has_export_section = ESMF_HConfigIsDefined(states_cfg, keyString=COMPONENT_EXPORT_STATE_SECTION, _RC) + _RETURN_UNLESS(has_export_section) + + ! For each field getting 'export'ed, check hconfig and use default_vert_profile if specified + export_cfg = ESMF_HConfigCreateAt(states_cfg, keyString=COMPONENT_EXPORT_STATE_SECTION, _RC) + b = ESMF_HConfigIterBegin(export_cfg, _RC) + e = ESMF_HConfigIterEnd(export_cfg, _RC) + iter = b + do while (ESMF_HConfigIterLoop(iter, b, e)) + field_name = ESMF_HConfigAsStringMapKey(iter, _RC) + ! print *, "FIELD: ", field_name + field_cfg = ESMF_HConfigCreateAtMapVal(iter, _RC) + has_default_vert_profile = ESMF_HConfigIsDefined(field_cfg, keyString=KEY_DEFAULT_VERT_PROFILE, _RC) + if (has_default_vert_profile) then + default_vert_profile = ESMF_HConfigAsR4Seq(field_cfg, keyString=KEY_DEFAULT_VERT_PROFILE, _RC) + call MAPL_GetPointer(exportState, ptr3d, trim(field_name), _RC) + shape_ = shape(ptr3d) + _ASSERT(shape_(3) == size(default_vert_profile), "incorrect size of vertical profile") + print *, ptr3d(1, 4, 3) + do concurrent(ii = 1:shape_(1), jj=1:shape_(2)) + ptr3d(ii, jj, :) = default_vert_profile + end do + print *, ptr3d(1, 4, 3) + end if + end do _RETURN(_SUCCESS) - _UNUSED_DUMMY(gridcomp) _UNUSED_DUMMY(importState) - _UNUSED_DUMMY(exportState) _UNUSED_DUMMY(clock) end subroutine init @@ -58,12 +100,12 @@ recursive subroutine run(gridcomp, importState, exportState, clock, rc) _UNUSED_DUMMY(clock) end subroutine run -end module ConfigurableGridComp +end module Mapl3g_ConfigurableGridComp subroutine setServices(gridcomp, rc) use ESMF use MAPL_ErrorHandlingMod - use ConfigurableGridComp, only: Configurable_setServices => SetServices + use mapl3g_ConfigurableGridComp, only: Configurable_setServices => SetServices type(ESMF_GridComp) :: gridcomp integer, intent(out) :: rc diff --git a/state/CMakeLists.txt b/state/CMakeLists.txt new file mode 100644 index 000000000000..46ec91f0fe4b --- /dev/null +++ b/state/CMakeLists.txt @@ -0,0 +1,21 @@ +esma_set_this (OVERRIDE MAPL.state) + +set(srcs + StateGet.F90 +) + +list (APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") + +if (BUILD_WITH_PFLOGGER) + find_package (PFLOGGER REQUIRED) +endif () + +esma_add_library(${this} + SRCS ${srcs} + DEPENDENCIES MAPL.shared ESMF::ESMF + TYPE SHARED + ) + +# if (PFUNIT_FOUND) +# add_subdirectory(tests EXCLUDE_FROM_ALL) +# endif () diff --git a/state/StateGet.F90 b/state/StateGet.F90 new file mode 100644 index 000000000000..4ea61d90a277 --- /dev/null +++ b/state/StateGet.F90 @@ -0,0 +1,50 @@ +#include "MAPL_Generic.h" + +module mapl3g_StateGet + + use mapl_ErrorHandling + use esmf + + implicit none + private + + public :: MAPL_StateGet + + interface MAPL_StateGet + procedure get_bundle_from_state_ + end interface MAPL_StateGet + +contains + + type(ESMF_FieldBundle) function get_bundle_from_state_(state, rc) result(bundle) + type(ESMF_State), intent(in) :: state + integer, optional, intent(out) :: rc + + character(len=ESMF_MAXSTR), allocatable :: item_name(:) + type (ESMF_StateItem_Flag), allocatable :: item_type(:) + type(ESMF_Field) :: field + type(ESMF_FieldStatus_Flag) :: field_status + integer :: item_count, idx, status + + ! bundle to pack fields in + bundle = ESMF_FieldBundleCreate(_RC) + call ESMF_StateGet(state, itemCount=item_count, _RC) + allocate(item_name(item_count), _STAT) + allocate(item_type(item_count), _STAT) + call ESMF_StateGet(state, itemNameList=item_name, itemTypeList=item_type, _RC) + do idx = 1, item_count + if (item_type(idx) /= ESMF_STATEITEM_FIELD) then + _FAIL("FieldBundle has not been implemented yet") + end if + call ESMF_StateGet(state, item_name(idx), field, _RC) + call ESMF_FieldGet(field, status=field_status, _RC) + if (field_status == ESMF_FIELDSTATUS_COMPLETE) then + call ESMF_FieldBundleAdd(bundle, [field], _RC) + end if + end do + deallocate(item_name, item_type, _STAT) + + _RETURN(_SUCCESS) + end function get_bundle_from_state_ + +end module mapl3g_StateGet