diff --git a/generic3g/OuterMetaComponent/initialize_advertise.F90 b/generic3g/OuterMetaComponent/initialize_advertise.F90 index 268cb6760400..8ffdf34c5f93 100644 --- a/generic3g/OuterMetaComponent/initialize_advertise.F90 +++ b/generic3g/OuterMetaComponent/initialize_advertise.F90 @@ -1,7 +1,9 @@ #include "MAPL_Generic.h" submodule (mapl3g_OuterMetaComponent) initialize_advertise_smod - implicit none + use mapl3g_make_ItemSpec + implicit none (type, external) + contains @@ -78,7 +80,7 @@ end subroutine self_advertise subroutine advertise_variable(var_spec, registry, geom, vertical_grid, unusable, rc) type(VariableSpec), intent(in) :: var_spec - type(StateRegistry), intent(inout) :: registry + type(StateRegistry), target, intent(inout) :: registry type(ESMF_Geom), optional, intent(in) :: geom class(VerticalGrid), optional, intent(in) :: vertical_grid class(KE), optional, intent(in) :: unusable @@ -91,8 +93,11 @@ subroutine advertise_variable(var_spec, registry, geom, vertical_grid, unusable, _ASSERT(var_spec%itemtype /= MAPL_STATEITEM_UNKNOWN, 'Invalid type id in variable spec <'//var_spec%short_name//'>.') - allocate(item_spec, source=var_spec%make_ItemSpec(geom, vertical_grid, registry, rc=status)); _VERIFY(status) + allocate(item_spec, source=make_ItemSpec(var_spec, registry, rc=status)) + _VERIFY(status) call item_spec%create(_RC) + call item_spec%initialize(geom, vertical_grid, _RC) + virtual_pt = var_spec%make_virtualPt() call registry%add_primary_spec(virtual_pt, item_spec) diff --git a/generic3g/specs/BracketSpec.F90 b/generic3g/specs/BracketSpec.F90 index d64d5bef9981..95ae7ebcc7e9 100644 --- a/generic3g/specs/BracketSpec.F90 +++ b/generic3g/specs/BracketSpec.F90 @@ -46,6 +46,7 @@ module mapl3g_BracketSpec procedure :: extension_cost procedure :: make_extension + procedure :: initialize => initialize_bracket_spec end type BracketSpec interface BracketSpec @@ -291,5 +292,14 @@ subroutine make_extension(this, dst_spec, new_spec, action, rc) _FAIL('not implemented') end subroutine make_extension + subroutine initialize_bracket_spec(this, geom, vertical_grid, rc) + class(BracketSpec), intent(inout) :: this + type(ESMF_Geom), optional, intent(in) :: geom + class(VerticalGrid), optional, intent(in) :: vertical_grid + integer, optional, intent(out) :: rc + integer :: status + + _RETURN(_SUCCESS) + end subroutine initialize_bracket_spec end module mapl3g_BracketSpec diff --git a/generic3g/specs/CMakeLists.txt b/generic3g/specs/CMakeLists.txt index 99d1eeec4080..e12c06936312 100644 --- a/generic3g/specs/CMakeLists.txt +++ b/generic3g/specs/CMakeLists.txt @@ -29,4 +29,5 @@ target_sources(MAPL.generic3g PRIVATE ComponentSpec.F90 AbstractActionSpec.F90 + make_itemSpec.F90 ) diff --git a/generic3g/specs/FieldSpec.F90 b/generic3g/specs/FieldSpec.F90 index 6ec4232bbb44..9a1a099d090c 100644 --- a/generic3g/specs/FieldSpec.F90 +++ b/generic3g/specs/FieldSpec.F90 @@ -1,5 +1,15 @@ #include "MAPL_Generic.h" +#if defined _SET_FIELD +# undef _SET_FIELD +#endif +#define _SET_FIELD(A, B, F) A%F = B%F + +#if defined(_SET_ALLOCATED_FIELD) +# undef _SET_ALLOCATED_FIELD +#endif +#define _SET_ALLOCATED_FIELD(A, B, F) if(allocated(B%F)) _SET_FIELD(A, B, F) + module mapl3g_FieldSpec use mapl3g_StateItemSpec @@ -27,6 +37,7 @@ module mapl3g_FieldSpec use mapl3g_geom_mgr, only: MAPL_SameGeom use mapl3g_FieldDictionary use mapl3g_GriddedComponentDriver + use mapl3g_VariableSpec use udunits2f, only: UDUNITS_are_convertible => are_convertible, udunit use gftl2_StringVector use esmf @@ -77,6 +88,7 @@ module mapl3g_FieldSpec type(ESMF_Field) :: payload real, allocatable :: default_value + type(VariableSpec) :: variable_spec logical :: is_created = .false. @@ -96,11 +108,13 @@ module mapl3g_FieldSpec procedure :: make_extension procedure :: set_info + procedure :: initialize => initialize_field_spec end type FieldSpec interface FieldSpec module procedure new_FieldSpec_geom + module procedure new_FieldSpec_varspec !# module procedure new_FieldSpec_defaults end interface FieldSpec @@ -131,7 +145,6 @@ module mapl3g_FieldSpec contains - function new_FieldSpec_geom(unusable, geom, vertical_grid, vertical_dim_spec, typekind, ungridded_dims, & standard_name, long_name, units, & attributes, regrid_param, default_value) result(field_spec) @@ -176,6 +189,17 @@ function new_FieldSpec_geom(unusable, geom, vertical_grid, vertical_dim_spec, ty end function new_FieldSpec_geom + function new_FieldSpec_varspec(variable_spec) result(field_spec) + type(FieldSpec) :: field_spec + class(VariableSpec), intent(in) :: variable_spec + + field_spec%variable_spec = variable_spec + field_spec%long_name = ' ' + !wdb fixme deleteme long_name is set here based on the VariableSpec + ! make_FieldSpec method + + end function new_FieldSpec_varspec + function get_regrid_method_(stdname, rc) result(regrid_method) type(ESMF_RegridMethod_Flag) :: regrid_method character(:), allocatable, intent(in) :: stdname @@ -198,6 +222,44 @@ function get_regrid_method_(stdname, rc) result(regrid_method) _RETURN(_SUCCESS) end function get_regrid_method_ + subroutine initialize_field_spec(this, geom, vertical_grid, rc) + class(FieldSpec), intent(inout) :: this + type(ESMF_Geom), optional, intent(in) :: geom + class(VerticalGrid), optional, intent(in) :: vertical_grid + integer, optional, intent(out) :: rc + integer :: status + type(ESMF_RegridMethod_Flag), allocatable :: regrid_method + type(ActualPtVector) :: dependencies + + associate (variable_spec => this%variable_spec) + if (present(geom)) this%geom = geom + if (present(vertical_grid)) this%vertical_grid = vertical_grid + + _SET_FIELD(this, variable_spec, vertical_dim_spec) + _SET_FIELD(this, variable_spec, typekind) + _SET_FIELD(this, variable_spec, ungridded_dims) + _SET_FIELD(this, variable_spec, attributes) + _SET_ALLOCATED_FIELD(this, variable_spec, standard_name) + _SET_ALLOCATED_FIELD(this, variable_spec, units) + _SET_ALLOCATED_FIELD(this, variable_spec, default_value) + + this%regrid_param = EsmfRegridderParam() ! use default regrid method + regrid_method = get_regrid_method_(this%standard_name) + this%regrid_param = EsmfRegridderParam(regridmethod=regrid_method) + + dependencies = variable_spec%make_dependencies(_RC) + call this%set_dependencies(dependencies) + call this%set_raw_dependencies(variable_spec%dependencies) + + if (variable_spec%state_intent == ESMF_STATEINTENT_INTERNAL) then + call this%set_active() + end if + end associate + + _RETURN(_SUCCESS) + + end subroutine initialize_field_spec + !# function new_FieldSpec_defaults(ungridded_dims, geom, units) result(field_spec) !# type(FieldSpec) :: field_spec !# type(ExtraDimsSpec), intent(in) :: ungridded_dims @@ -961,5 +1023,7 @@ subroutine set_info(this, field, rc) _RETURN(_SUCCESS) end subroutine set_info - + end module mapl3g_FieldSpec +#undef _SET_FIELD +#undef _SET_ALLOCATED_FIELD diff --git a/generic3g/specs/InvalidSpec.F90 b/generic3g/specs/InvalidSpec.F90 index 5e871b87f559..fb4baa23b2fd 100644 --- a/generic3g/specs/InvalidSpec.F90 +++ b/generic3g/specs/InvalidSpec.F90 @@ -9,6 +9,7 @@ module mapl3g_InvalidSpec use mapl3g_ActualPtVector use mapl3g_ActualPtSpecPtrMap use mapl3g_NullAction + use mapl3g_VerticalGrid use esmf, only: ESMF_FieldBundle use esmf, only: ESMF_Geom use esmf, only: ESMF_State @@ -35,6 +36,7 @@ module mapl3g_InvalidSpec procedure :: make_extension procedure :: extension_cost + procedure :: initialize => initialize_invalid_spec end type InvalidSpec @@ -154,4 +156,16 @@ integer function extension_cost(this, src_spec, rc) result(cost) end function extension_cost + subroutine initialize_invalid_spec(this, geom, vertical_grid, rc) + class(InvalidSpec), intent(inout) :: this + type(ESMF_Geom), optional, intent(in) :: geom + class(VerticalGrid), optional, intent(in) :: vertical_grid + integer, optional, intent(out) :: rc + + integer :: status + + _FAIL('Attempt to initialize item of type InvalidSpec') + + end subroutine initialize_invalid_spec + end module mapl3g_InvalidSpec diff --git a/generic3g/specs/ServiceSpec.F90 b/generic3g/specs/ServiceSpec.F90 index 5ac9f2156f48..bad70be7fc82 100644 --- a/generic3g/specs/ServiceSpec.F90 +++ b/generic3g/specs/ServiceSpec.F90 @@ -1,9 +1,12 @@ #include "MAPL_Generic.h" module mapl3g_ServiceSpec + use mapl3g_StateRegistry + use mapl3g_VariableSpec use mapl3g_StateItemSpec use mapl3g_MultiState use mapl3g_ActualConnectionPt + use mapl3g_StateItemExtension use mapl3g_ExtensionAction use mapl3g_NullAction use mapl3g_AbstractActionSpec @@ -14,6 +17,7 @@ module mapl3g_ServiceSpec use mapl3g_ActualPtVector use mapl3g_ActualConnectionPt use mapl3g_VirtualConnectionPt + use mapl3g_VerticalGrid use esmf use gftl2_StringVector implicit none @@ -23,6 +27,8 @@ module mapl3g_ServiceSpec type, extends(StateItemSpec) :: ServiceSpec private + type(StateRegistry), pointer :: registry + type(VariableSpec) :: variable_spec type(ESMF_Typekind_Flag), allocatable :: typekind type(ESMF_FieldBundle) :: payload type(StateItemSpecPtr), allocatable :: dependency_specs(:) @@ -38,6 +44,7 @@ module mapl3g_ServiceSpec procedure :: extension_cost procedure :: add_to_state procedure :: add_to_bundle + procedure :: initialize => initialize_service_spec !!$ procedure :: check_complete end type ServiceSpec @@ -47,13 +54,13 @@ module mapl3g_ServiceSpec contains - function new_ServiceSpec(service_item_specs) result(spec) + function new_ServiceSpec(variable_spec, registry) result(spec) type(ServiceSpec) :: spec - type(StateItemSpecPtr), intent(in) :: service_item_specs(:) + type(VariableSpec), intent(in) :: variable_spec + type(StateRegistry), target, intent(in) :: registry - integer :: status - - spec%dependency_specs = service_item_specs + spec%variable_spec = variable_spec + spec%registry => registry end function new_ServiceSpec @@ -197,7 +204,33 @@ integer function extension_cost(this, src_spec, rc) result(cost) cost = 0 _RETURN(_SUCCESS) end function extension_cost - + subroutine initialize_service_spec(this, geom, vertical_grid, rc) + class(ServiceSpec), intent(inout) :: this + type(ESMF_Geom), optional, intent(in) :: geom + class(VerticalGrid), optional, intent(in) :: vertical_grid + integer, optional, intent(out) :: rc + integer :: status + + integer :: i, n + type(StateItemSpecPtr), allocatable :: specs(:) + type(VirtualConnectionPt) :: v_pt + type(StateItemExtension), pointer :: primary + + associate (var_spec => this%variable_spec) + n = var_spec%service_items%size() + allocate(specs(n)) + + do i = 1, n + v_pt = VirtualConnectionPt(ESMF_STATEINTENT_INTERNAL, var_spec%service_items%of(i)) + ! Internal items are always unique and "primary" (owned by user) + primary => this%registry%get_primary_extension(v_pt, _RC) + specs(i)%ptr => primary%get_spec() + end do + end associate + this%dependency_specs = specs + + _RETURN(_SUCCESS) + end subroutine initialize_service_spec end module mapl3g_ServiceSpec diff --git a/generic3g/specs/StateItemSpec.F90 b/generic3g/specs/StateItemSpec.F90 index 5ca0e21958d7..c36eef5d6c7e 100644 --- a/generic3g/specs/StateItemSpec.F90 +++ b/generic3g/specs/StateItemSpec.F90 @@ -31,6 +31,7 @@ module mapl3g_StateItemSpec procedure(I_add_to_state), deferred :: add_to_state procedure(I_add_to_bundle), deferred :: add_to_bundle + procedure(I_initialize), deferred :: initialize procedure, non_overridable :: set_allocated procedure, non_overridable :: is_allocated @@ -47,7 +48,6 @@ module mapl3g_StateItemSpec class(StateItemSpec), pointer :: ptr => null() end type StateItemSpecPtr - abstract interface subroutine I_connect(this, src_spec, actual_pt, rc) @@ -122,6 +122,16 @@ subroutine I_add_to_bundle(this, bundle, rc) integer, optional, intent(out) :: rc end subroutine I_add_to_bundle + subroutine I_initialize(this, geom, vertical_grid, rc) + use esmf, only: ESMF_Geom + use mapl3g_VerticalGrid, only: VerticalGrid + import StateItemSpec + class(StateItemSpec), intent(inout) :: this + type(ESMF_Geom), optional, intent(in) :: geom + class(VerticalGrid), optional, intent(in) :: vertical_grid + integer, optional, intent(out) :: rc + end subroutine I_initialize + end interface contains diff --git a/generic3g/specs/StateSpec.F90 b/generic3g/specs/StateSpec.F90 index 9158b55459ae..9ee91c01e17d 100644 --- a/generic3g/specs/StateSpec.F90 +++ b/generic3g/specs/StateSpec.F90 @@ -5,6 +5,7 @@ module mapl3g_StateSpec use mapl3g_AbstractActionSpec use mapl3g_StateItemSpecMap use mapl3g_VariableSpec + use mapl3g_VerticalGrid use mapl3g_MultiState use mapl3g_ActualConnectionPt use mapl3g_ActualPtVector @@ -22,7 +23,7 @@ module mapl3g_StateSpec type(ESMF_State) :: payload type(StateItemSpecMap) :: item_specs contains -!!$ procedure :: initialize + procedure :: initialize procedure :: add_item procedure :: get_item @@ -42,20 +43,18 @@ module mapl3g_StateSpec contains -!!$ ! Nothing defined at this time. -!!$ subroutine initialize(this, geom, var_spec, unusable, rc) -!!$ class(StateSpec), intent(inout) :: this -!!$ type(ESMF_Geom), intent(in) :: geom -!!$ type(VariableSpec), intent(in) :: var_spec -!!$ class(KeywordEnforcer), optional, intent(in) :: unusable -!!$ integer, optional, intent(out) :: rc -!!$ -!!$ character(:), allocatable :: units -!!$ integer :: status -!!$ -!!$ _RETURN(_SUCCESS) -!!$ _UNUSED_DUMMY(unusable) -!!$ end subroutine initialize + ! Nothing defined at this time. + subroutine initialize(this, geom, vertical_grid, rc) + class(StateSpec), intent(inout) :: this + type(ESMF_Geom), optional, intent(in) :: geom + class(VerticalGrid), optional, intent(in) :: vertical_grid + integer, optional, intent(out) :: rc + + character(:), allocatable :: units + integer :: status + + _RETURN(_SUCCESS) + end subroutine initialize subroutine add_item(this, name, item) class(StateSpec), target, intent(inout) :: this diff --git a/generic3g/specs/VariableSpec.F90 b/generic3g/specs/VariableSpec.F90 index 3a14ba9d8936..802887aae3b0 100644 --- a/generic3g/specs/VariableSpec.F90 +++ b/generic3g/specs/VariableSpec.F90 @@ -3,17 +3,9 @@ module mapl3g_VariableSpec - use mapl3g_StateItemSpec - use mapl3g_StateItem - use mapl3g_StateItemExtension use mapl3g_UngriddedDims use mapl3g_VerticalDimSpec use mapl3g_HorizontalDimsSpec - use mapl3g_FieldSpec - use mapl3g_WildcardSpec - use mapl3g_BracketSpec - use mapl3g_ServiceSpec - use mapl3g_InvalidSpec use mapl3g_VirtualConnectionPt use mapl3g_ActualConnectionPt use mapl3g_VerticalGrid @@ -21,6 +13,7 @@ module mapl3g_VariableSpec use mapl3g_ActualPtVector use mapl_ErrorHandling use mapl3g_StateRegistry + use mapl3g_StateItem use esmf use gFTL2_StringVector use nuopc @@ -58,18 +51,20 @@ module mapl3g_VariableSpec type(StringVector) :: dependencies contains procedure :: make_virtualPt - procedure :: make_ItemSpec_new - generic :: make_itemSpec => make_itemSpec_new - procedure :: make_BracketSpec - procedure :: make_FieldSpec - procedure :: make_ServiceSpec_new - procedure :: make_WildcardSpec + !wdb fixme deleteme These are obsolete because StateItemSpec is performing these actions +! procedure :: make_ItemSpec_new +! generic :: make_itemSpec => make_itemSpec_new +! procedure :: make_BracketSpec +! procedure :: make_FieldSpec +! procedure :: make_ServiceSpec_new +! procedure :: make_WildcardSpec procedure :: make_dependencies procedure, private :: pick_geom_ !!$ procedure :: make_StateSpec !!$ procedure :: make_BundleSpec !!$ procedure :: initialize + procedure :: initialize end type VariableSpec interface VariableSpec @@ -190,55 +185,56 @@ function make_virtualPt(this) result(v_pt) end if end function make_virtualPt + !wdb fixme deleteme This is obsolete. ! This implementation ensures that an object is at least created ! even if failures are encountered. This is necessary for ! robust error handling upstream. - function make_ItemSpec_new(this, geom, vertical_grid, registry, rc) result(item_spec) - class(StateItemSpec), allocatable :: item_spec - class(VariableSpec), intent(in) :: this - type(ESMF_Geom), optional, intent(in) :: geom - class(VerticalGrid), optional, intent(in) :: vertical_grid - type(StateRegistry), intent(in) :: registry - integer, optional, intent(out) :: rc - - integer :: status - type(ActualPtVector) :: dependencies - type(ESMF_Geom), allocatable :: geom_local - - call this%pick_geom_(geom, geom_local, _RC) - - select case (this%itemtype%ot) - case (MAPL_STATEITEM_FIELD%ot) - allocate(FieldSpec::item_spec) - item_spec = this%make_FieldSpec(geom_local, vertical_grid, _RC) +! function make_ItemSpec_new(this, geom, vertical_grid, registry, rc) result(item_spec) +! class(StateItemSpec), allocatable :: item_spec +! class(VariableSpec), intent(in) :: this +! type(ESMF_Geom), optional, intent(in) :: geom +! class(VerticalGrid), optional, intent(in) :: vertical_grid +! type(StateRegistry), intent(in) :: registry +! integer, optional, intent(out) :: rc +! +! integer :: status +! type(ActualPtVector) :: dependencies +! type(ESMF_Geom), allocatable :: geom_local +! +! call this%pick_geom_(geom, geom_local, _RC) +! +! select case (this%itemtype%ot) +! case (MAPL_STATEITEM_FIELD%ot) +! allocate(FieldSpec::item_spec) +! item_spec = this%make_FieldSpec(geom_local, vertical_grid, _RC) !!$ case (MAPL_STATEITEM_FIELDBUNDLE) !!$ allocate(FieldBundleSpec::item_spec) !!$ item_spec = this%make_FieldBundleSpec(geom, _RC) - case (MAPL_STATEITEM_SERVICE%ot) - allocate(ServiceSpec::item_spec) - item_spec = this%make_ServiceSpec_new(registry, _RC) - case (MAPL_STATEITEM_WILDCARD%ot) - allocate(WildcardSpec::item_spec) - item_spec = this%make_WildcardSpec(geom_local, vertical_grid, _RC) - case (MAPL_STATEITEM_BRACKET%ot) - allocate(BracketSpec::item_spec) - item_spec = this%make_BracketSpec(geom_local, vertical_grid, _RC) - case default - ! Fail, but still need to allocate a result. - allocate(InvalidSpec::item_spec) - _FAIL('Unsupported type.') - end select - - dependencies = this%make_dependencies(_RC) - call item_spec%set_dependencies(dependencies) - call item_spec%set_raw_dependencies(this%dependencies) - - if (this%state_intent == ESMF_STATEINTENT_INTERNAL) then - call item_spec%set_active() - end if - - _RETURN(_SUCCESS) - end function make_ItemSpec_new +! case (MAPL_STATEITEM_SERVICE%ot) +! allocate(ServiceSpec::item_spec) +! item_spec = this%make_ServiceSpec_new(registry, _RC) +! case (MAPL_STATEITEM_WILDCARD%ot) +! allocate(WildcardSpec::item_spec) +! item_spec = this%make_WildcardSpec(geom_local, vertical_grid, _RC) +! case (MAPL_STATEITEM_BRACKET%ot) +! allocate(BracketSpec::item_spec) +! item_spec = this%make_BracketSpec(geom_local, vertical_grid, _RC) +! case default +! ! Fail, but still need to allocate a result. +! allocate(InvalidSpec::item_spec) +! _FAIL('Unsupported type.') +! end select +! +! dependencies = this%make_dependencies(_RC) +! call item_spec%set_dependencies(dependencies) +! call item_spec%set_raw_dependencies(this%dependencies) +! +! if (this%state_intent == ESMF_STATEINTENT_INTERNAL) then +! call item_spec%set_active() +! end if +! +! _RETURN(_SUCCESS) +! end function make_ItemSpec_new subroutine pick_geom_(this, that_geom, geom, rc) class(VariableSpec), intent(in) :: this @@ -257,48 +253,49 @@ subroutine pick_geom_(this, that_geom, geom, rc) _RETURN(_SUCCESS) end subroutine pick_geom_ - function make_BracketSpec(this, geom, vertical_grid, rc) result(bracket_spec) - type(BracketSpec) :: bracket_spec - class(VariableSpec), intent(in) :: this - type(ESMF_Geom), optional, intent(in) :: geom - class(VerticalGrid), intent(in) :: vertical_grid - integer, optional, intent(out) :: rc - - integer :: status - character(:), allocatable :: units - type(FieldSpec) :: field_spec - - if (.not. valid(this)) then - _RETURN(_FAILURE) - end if - - call fill_units(this, units, _RC) - - field_spec = FieldSpec(geom=geom, vertical_grid=vertical_grid, vertical_dim_spec=this%vertical_dim_spec, ungridded_dims=this%ungridded_dims, & - typekind=this%typekind, & - standard_name=this%standard_name, long_name=' ', units=units, attributes=this%attributes, default_value=this%default_value) - - - bracket_spec = BracketSpec(field_spec, this%bracket_size) - - _RETURN(_SUCCESS) - - contains - - logical function valid(this) result(is_valid) - class(VariableSpec), intent(in) :: this - - is_valid = .false. ! unless - - if (.not. this%itemtype == MAPL_STATEITEM_BRACKET) return - if (.not. allocated(this%standard_name)) return - if (.not. allocated(this%bracket_size)) return - - is_valid = .true. - - end function valid - - end function make_BracketSpec + !wdb fixme deleteme This is obsolete. Should be moved to constructor/initialize for BracketSpec. +! function make_BracketSpec(this, geom, vertical_grid, rc) result(bracket_spec) +! type(BracketSpec) :: bracket_spec +! class(VariableSpec), intent(in) :: this +! type(ESMF_Geom), optional, intent(in) :: geom +! class(VerticalGrid), intent(in) :: vertical_grid +! integer, optional, intent(out) :: rc +! +! integer :: status +! character(:), allocatable :: units +! type(FieldSpec) :: field_spec +! +! if (.not. valid(this)) then +! _RETURN(_FAILURE) +! end if +! +! call fill_units(this, units, _RC) +! +! field_spec = FieldSpec(geom=geom, vertical_grid=vertical_grid, vertical_dim_spec=this%vertical_dim_spec, ungridded_dims=this%ungridded_dims, & +! typekind=this%typekind, & +! standard_name=this%standard_name, long_name=' ', units=units, attributes=this%attributes, default_value=this%default_value) +! +! +! bracket_spec = BracketSpec(field_spec, this%bracket_size) +! +! _RETURN(_SUCCESS) +! +! contains +! +! logical function valid(this) result(is_valid) +! class(VariableSpec), intent(in) :: this +! +! is_valid = .false. ! unless +! +! if (.not. this%itemtype == MAPL_STATEITEM_BRACKET) return +! if (.not. allocated(this%standard_name)) return +! if (.not. allocated(this%bracket_size)) return +! +! is_valid = .true. +! +! end function valid +! +! end function make_BracketSpec subroutine fill_units(this, units, rc) class(VariableSpec), intent(in) :: this @@ -324,122 +321,125 @@ subroutine fill_units(this, units, rc) _RETURN(_SUCCESS) end subroutine fill_units - function make_FieldSpec(this, geom, vertical_grid, rc) result(field_spec) - type(FieldSpec) :: field_spec - class(VariableSpec), intent(in) :: this - type(ESMF_Geom), optional, intent(in) :: geom - class(VerticalGrid), optional, intent(in) :: vertical_grid - integer, optional, intent(out) :: rc - - integer :: status - character(:), allocatable :: units - - if (.not. valid(this)) then - _RETURN(_FAILURE) - end if - - _ASSERT(this%vertical_dim_spec /= VERTICAL_DIM_UNKNOWN, 'must provide a vertical dim spec') - call fill_units(this, units, _RC) - - field_spec = FieldSpec(geom=geom, vertical_grid=vertical_grid, vertical_dim_spec=this%vertical_dim_spec, ungridded_dims=this%ungridded_dims, & - typekind=this%typekind, & - standard_name=this%standard_name, long_name=' ', units=units, attributes=this%attributes, default_value=this%default_value) - - _RETURN(_SUCCESS) - - contains - - logical function valid(this) result(is_valid) - class(VariableSpec), intent(in) :: this - - is_valid = .false. ! unless - - if (.not. this%itemtype == MAPL_STATEITEM_FIELD) return + !wdb fixme deleteme This is obsolete. +! function make_FieldSpec(this, geom, vertical_grid, rc) result(field_spec) +! type(FieldSpec) :: field_spec +! class(VariableSpec), intent(in) :: this +! type(ESMF_Geom), optional, intent(in) :: geom +! class(VerticalGrid), optional, intent(in) :: vertical_grid +! integer, optional, intent(out) :: rc +! +! integer :: status +! character(:), allocatable :: units +! +! if (.not. valid(this)) then +! _RETURN(_FAILURE) +! end if +! +! _ASSERT(this%vertical_dim_spec /= VERTICAL_DIM_UNKNOWN, 'must provide a vertical dim spec') +! call fill_units(this, units, _RC) +! +! field_spec = FieldSpec(geom=geom, vertical_grid=vertical_grid, vertical_dim_spec=this%vertical_dim_spec, ungridded_dims=this%ungridded_dims, & +! typekind=this%typekind, & +! standard_name=this%standard_name, long_name=' ', units=units, attributes=this%attributes, default_value=this%default_value) +! +! _RETURN(_SUCCESS) +! +! contains +! +! logical function valid(this) result(is_valid) +! class(VariableSpec), intent(in) :: this +! +! is_valid = .false. ! unless +! +! if (.not. this%itemtype == MAPL_STATEITEM_FIELD) return !# if (.not. allocated(this%standard_name)) return - - is_valid = .true. - - end function valid - - end function make_FieldSpec - +! +! is_valid = .true. +! +! end function valid +! +! end function make_FieldSpec + + !wdb fixme deleteme This needs to be moved to constructor/initialize for ServiceSpec. ! ------ ! ServiceSpec needs reference to the specs of the fields that are to be ! handled by the service. Shallow copy of these will appear in the FieldBundle in the ! import state of the requesting gridcomp. ! ------ - function make_ServiceSpec_new(this, registry, rc) result(service_spec) - type(ServiceSpec) :: service_spec - class(VariableSpec), intent(in) :: this - type(StateRegistry), target, intent(in) :: registry - integer, optional, intent(out) :: rc - - integer :: status - integer :: i, n - type(StateItemSpecPtr), allocatable :: specs(:) - type(VirtualConnectionPt) :: v_pt - type(StateItemExtension), pointer :: primary - - if (.not. valid(this)) then - _RETURN(_FAILURE) - end if - - n = this%service_items%size() - allocate(specs(n)) - - do i = 1, n - v_pt = VirtualConnectionPt(ESMF_STATEINTENT_INTERNAL, this%service_items%of(i)) - ! Internal items are always unique and "primary" (owned by user) - primary => registry%get_primary_extension(v_pt, _RC) - specs(i)%ptr => primary%get_spec() - end do - service_spec = ServiceSpec(specs) - - _RETURN(_SUCCESS) - - contains - - logical function valid(this) result(is_valid) - class(VariableSpec), intent(in) :: this - - is_valid = .false. ! unless - if (.not. this%itemtype == MAPL_STATEITEM_SERVICE) return - is_valid = .true. - - end function valid - - end function make_ServiceSpec_new - - function make_WildcardSpec(this, geom, vertical_grid, rc) result(wildcard_spec) - type(WildcardSpec) :: wildcard_spec - class(VariableSpec), intent(in) :: this - type(ESMF_Geom), optional, intent(in) :: geom - class(VerticalGrid), intent(in) :: vertical_grid - integer, optional, intent(out) :: rc - - integer :: status - type(FieldSpec) :: field_spec - - field_spec = new_FieldSpec_geom(geom=geom, vertical_grid=vertical_grid, & - vertical_dim_spec=this%vertical_dim_spec, typekind=this%typekind, ungridded_dims=this%ungridded_dims, & - attributes=this%attributes, default_value=this%default_value) - wildcard_spec = WildCardSpec(field_spec) - - _RETURN(_SUCCESS) - contains - - logical function valid(this) result(is_valid) - class(VariableSpec), intent(in) :: this - - is_valid = .false. ! unless - if (allocated(this%standard_name)) return - if (allocated(this%units)) return ! maybe this can be relaxed - match only thisgs that have same units? - if (this%attributes%size() > 0) return - if (allocated(this%default_value)) return - is_valid = .true. - - end function valid - end function make_WildcardSpec +! function make_ServiceSpec_new(this, registry, rc) result(service_spec) +! type(ServiceSpec) :: service_spec +! class(VariableSpec), intent(in) :: this +! type(StateRegistry), target, intent(in) :: registry +! integer, optional, intent(out) :: rc +! +! integer :: status +! integer :: i, n +! type(StateItemSpecPtr), allocatable :: specs(:) +! type(VirtualConnectionPt) :: v_pt +! type(StateItemExtension), pointer :: primary +! +! if (.not. valid(this)) then +! _RETURN(_FAILURE) +! end if +! +! n = this%service_items%size() +! allocate(specs(n)) +! +! do i = 1, n +! v_pt = VirtualConnectionPt(ESMF_STATEINTENT_INTERNAL, this%service_items%of(i)) +! ! Internal items are always unique and "primary" (owned by user) +! primary => registry%get_primary_extension(v_pt, _RC) +! specs(i)%ptr => primary%get_spec() +! end do +! service_spec = ServiceSpec(specs) +! +! _RETURN(_SUCCESS) +! +! contains +! +! logical function valid(this) result(is_valid) +! class(VariableSpec), intent(in) :: this +! +! is_valid = .false. ! unless +! if (.not. this%itemtype == MAPL_STATEITEM_SERVICE) return +! is_valid = .true. +! +! end function valid +! +! end function make_ServiceSpec_new + + !wdb fixme deleteme This is obsolete. Needs to move to constructor/initialize for WildcardSpec. +! function make_WildcardSpec(this, geom, vertical_grid, rc) result(wildcard_spec) +! type(WildcardSpec) :: wildcard_spec +! class(VariableSpec), intent(in) :: this +! type(ESMF_Geom), optional, intent(in) :: geom +! class(VerticalGrid), intent(in) :: vertical_grid +! integer, optional, intent(out) :: rc +! +! integer :: status +! type(FieldSpec) :: field_spec +! +! field_spec = new_FieldSpec_geom(geom=geom, vertical_grid=vertical_grid, & +! vertical_dim_spec=this%vertical_dim_spec, typekind=this%typekind, ungridded_dims=this%ungridded_dims, & +! attributes=this%attributes, default_value=this%default_value) +! wildcard_spec = WildCardSpec(field_spec) +! +! _RETURN(_SUCCESS) +! contains +! +! logical function valid(this) result(is_valid) +! class(VariableSpec), intent(in) :: this +! +! is_valid = .false. ! unless +! if (allocated(this%standard_name)) return +! if (allocated(this%units)) return ! maybe this can be relaxed - match only thisgs that have same units? +! if (this%attributes%size() > 0) return +! if (allocated(this%default_value)) return +! is_valid = .true. +! +! end function valid +! end function make_WildcardSpec function make_dependencies(this, rc) result(dependencies) type(ActualPtVector) :: dependencies diff --git a/generic3g/specs/WildcardSpec.F90 b/generic3g/specs/WildcardSpec.F90 index 65fbf6706022..bba9abfc569c 100644 --- a/generic3g/specs/WildcardSpec.F90 +++ b/generic3g/specs/WildcardSpec.F90 @@ -11,6 +11,7 @@ module mapl3g_WildcardSpec use mapl3g_NullAction use mapl_ErrorHandling use mapl_KeywordEnforcer + use mapl3g_VerticalGrid use esmf use pFlogger @@ -34,6 +35,7 @@ module mapl3g_WildcardSpec procedure :: add_to_state procedure :: add_to_bundle procedure :: extension_cost + procedure :: initialize => initialize_wildcard_spec end type WildcardSpec @@ -234,4 +236,17 @@ integer function extension_cost(this, src_spec, rc) result(cost) _RETURN(_SUCCESS) end function extension_cost + subroutine initialize_wildcard_spec(this, geom, vertical_grid, rc) + class(WildcardSpec), intent(inout) :: this + type(ESMF_Geom), optional, intent(in) :: geom + class(VerticalGrid), optional, intent(in) :: vertical_grid + integer, optional, intent(out) :: rc + + integer :: status + + call this%reference_spec%initialize(geom, vertical_grid, _RC) + + _RETURN(_SUCCESS) + end subroutine initialize_wildcard_spec + end module mapl3g_WildcardSpec diff --git a/generic3g/specs/make_itemSpec.F90 b/generic3g/specs/make_itemSpec.F90 new file mode 100644 index 000000000000..920eff00c930 --- /dev/null +++ b/generic3g/specs/make_itemSpec.F90 @@ -0,0 +1,56 @@ +#include "MAPL_Generic.h" + +module mapl3g_make_itemSpec + use mapl3g_StateItemSpec + use mapl3g_StateItem + use mapl3g_FieldSpec, only: FieldSpec + use mapl3g_ServiceSpec, only: ServiceSpec + use mapl3g_WildcardSpec, only: WildcardSpec + use mapl3g_BracketSpec, only: BracketSpec + use mapl3g_StateSpec, only: StateSpec + use mapl3g_InvalidSpec, only: InvalidSpec + use mapl3g_StateRegistry, only: StateRegistry + use mapl_ErrorHandling + implicit none + private + public :: make_ItemSpec + +contains + + function make_itemSpec(variable_spec, registry, rc) result(item_spec) + use mapl3g_VariableSpec, only: VariableSpec + class(StateItemSpec), allocatable :: item_spec + class(VariableSpec), intent(in) :: variable_spec + type(StateRegistry), target, intent(in) :: registry + integer, optional, intent(out) :: rc + + integer :: status + type(FieldSpec) :: field_spec + + select case (variable_spec%itemtype%ot) + case (MAPL_STATEITEM_FIELD%ot) + allocate(FieldSpec :: item_spec) + item_spec = FieldSpec(variable_spec) + case (MAPL_STATEITEM_SERVICE%ot) + allocate(ServiceSpec :: item_spec) + item_spec = ServiceSpec(variable_spec, registry) + case (MAPL_STATEITEM_WILDCARD%ot) + allocate(WildcardSpec :: item_spec) + field_spec = FieldSpec(variable_spec) + item_spec = WildcardSpec(field_spec) + case (MAPL_STATEITEM_BRACKET%ot) + allocate(BracketSpec :: item_spec) + field_spec = FieldSpec(variable_spec) + item_spec = BracketSpec(field_spec, variable_spec%bracket_size) +!# case (MAPL_STATEITEM_STATE%ot) +!# allocate(StateSpec :: item_spec) + case default + allocate(InvalidSpec :: item_spec) + _FAIL('Unsupported type.') + end select + + _RETURN(_SUCCESS) + + end function make_itemSpec + +end module mapl3g_make_itemSpec diff --git a/generic3g/tests/MockItemSpec.F90 b/generic3g/tests/MockItemSpec.F90 index 56b5afa3a8fd..ee171eb89280 100644 --- a/generic3g/tests/MockItemSpec.F90 +++ b/generic3g/tests/MockItemSpec.F90 @@ -9,6 +9,7 @@ module MockItemSpecMod use mapl3g_ActualPtVector use mapl3g_ExtensionAction use mapl3g_NullAction + use mapl3g_VerticalGrid use mapl_ErrorHandling use mapl_KeywordEnforcer use esmf @@ -26,6 +27,7 @@ module MockItemSpecMod procedure :: create procedure :: destroy procedure :: allocate + procedure :: initialize => initialize_mockspec procedure :: connect_to procedure :: can_connect_to @@ -62,6 +64,15 @@ function new_MockItemSpec(name, subtype) result(spec) end function new_MockItemSpec + subroutine initialize_mockspec(this, geom, vertical_grid, rc) + class(MockItemSpec), intent(inout) :: this + type(ESMF_Geom), optional, intent(in) :: geom + class(VerticalGrid), optional, intent(in) :: vertical_grid + integer, optional, intent(out) :: rc + + _RETURN(_SUCCESS) + end subroutine initialize_mockspec + subroutine create(this, rc) class(MockItemSpec), intent(inout) :: this integer, optional, intent(out) :: rc diff --git a/generic3g/tests/Test_ModelVerticalGrid.pf b/generic3g/tests/Test_ModelVerticalGrid.pf index e71e92a8f10f..253df932c6be 100644 --- a/generic3g/tests/Test_ModelVerticalGrid.pf +++ b/generic3g/tests/Test_ModelVerticalGrid.pf @@ -19,13 +19,14 @@ module Test_ModelVerticalGrid use mapl3g_ComponentDriverVector use mapl3g_ComponentDriverPtrVector use mapl3g_MultiState + use mapl3g_make_ItemSpec use mapl3g_geom_mgr use mapl3g_CouplerMetaComponent, only: GENERIC_COUPLER_UPDATE use esmf ! testing framework use ESMF_TestMethod_mod use funit - implicit none + implicit none (type, external) integer, parameter :: IM=6, JM=7, LM=3 @@ -64,8 +65,10 @@ contains units='hPa', & vertical_dim_spec=VERTICAL_DIM_EDGE, & default_value=3.) - allocate(ple_spec, source=var_spec%make_itemSpec(geom=geom, vertical_grid=vgrid, registry=r, rc=status)) + allocate(ple_spec, source=make_itemSpec(var_spec, r, rc=status)) _VERIFY(status) + call ple_spec%initialize(geom=geom, vertical_grid=vgrid, _RC) + call r%add_primary_spec(ple_pt, ple_spec) extension => r%get_primary_extension(ple_pt, _RC)