diff --git a/generic3g/GenericGridComp.F90 b/generic3g/GenericGridComp.F90 index 66175f30d61f..9f0c824ba934 100644 --- a/generic3g/GenericGridComp.F90 +++ b/generic3g/GenericGridComp.F90 @@ -53,14 +53,7 @@ subroutine set_entry_points(gridcomp, rc) integer :: status integer :: phase - associate (phases => outer_meta%get_phases(ESMF_METHOD_RUN)) - do phase = 1, phases%size() - call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_RUN, run, phase=phase, _RC) - end do - end associate - ! Mandatory generic initialize phases - call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_INITIALIZE, initialize, phase=GENERIC_INIT_CLOCK, _RC) call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_INITIALIZE, initialize, phase=GENERIC_INIT_GEOM, _RC) call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_INITIALIZE, initialize, phase=GENERIC_INIT_ADVERTISE, _RC) call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_INITIALIZE, initialize, phase=GENERIC_INIT_POST_ADVERTISE, _RC) @@ -68,6 +61,14 @@ subroutine set_entry_points(gridcomp, rc) !# call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_INITIALIZE, initialize, phase=GENERIC_INIT_RESTORE, _RC) call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_INITIALIZE, initialize, phase=GENERIC_INIT_USER, _RC) + ! Run phases, including mandatory + call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_RUN, run, phase=GENERIC_RUN_CLOCK_ADVANCE, _RC) + associate (phases => outer_meta%get_phases(ESMF_METHOD_RUN)) + do phase = 1, phases%size() + call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_RUN, run, phase=phase, _RC) + end do + end associate + call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_FINALIZE, finalize, _RC) !# call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_READRESTART, read_restart, _RC) !# call ESMF_GridCompSetEntryPoint(gridcomp, ESMF_METHOD_WRITERESTART, write_restart, _RC) @@ -149,20 +150,18 @@ recursive subroutine initialize(gridcomp, importState, exportState, clock, rc) outer_meta => get_outer_meta(gridcomp, _RC) call ESMF_GridCompGet(gridcomp, currentPhase=phase, _RC) select case (phase) - case (GENERIC_INIT_CLOCK) - call outer_meta%initialize_clock(clock, _RC) case (GENERIC_INIT_GEOM) - call outer_meta%initialize_geom(clock, _RC) + call outer_meta%initialize_geom(_RC) case (GENERIC_INIT_ADVERTISE) - call outer_meta%initialize_advertise(clock, _RC) + call outer_meta%initialize_advertise(_RC) case (GENERIC_INIT_POST_ADVERTISE) call outer_meta%initialize_post_advertise(importState, exportState, clock, _RC) case (GENERIC_INIT_REALIZE) - call outer_meta%initialize_realize(clock, _RC) + call outer_meta%initialize_realize(_RC) !# case (GENERIC_INIT_RESTORE) -!# call outer_meta%initialize_realize(clock, _RC) +!# call outer_meta%initialize_realize(_RC) case (GENERIC_INIT_USER) - call outer_meta%initialize_user(clock, _RC) + call outer_meta%initialize_user(_RC) case default _FAIL('Unknown generic phase ') end select @@ -191,7 +190,7 @@ recursive subroutine run(gridcomp, importState, exportState, clock, rc) phases => outer_meta%get_phases(ESMF_METHOD_RUN) phase_name => phases%of(phase) - call outer_meta%run(clock, phase_name=phase_name, _RC) + call outer_meta%run(phase_name=phase_name, _RC) _RETURN(ESMF_SUCCESS) end subroutine run diff --git a/generic3g/GenericPhases.F90 b/generic3g/GenericPhases.F90 index 2464032ceee2..86b6492d538d 100644 --- a/generic3g/GenericPhases.F90 +++ b/generic3g/GenericPhases.F90 @@ -4,31 +4,37 @@ module mapl3g_GenericPhases ! Named constants public :: GENERIC_INIT_PHASE_SEQUENCE - public :: GENERIC_INIT_CLOCK public :: GENERIC_INIT_GEOM public :: GENERIC_INIT_ADVERTISE public :: GENERIC_INIT_POST_ADVERTISE public :: GENERIC_INIT_REALIZE public :: GENERIC_INIT_USER + public :: GENERIC_RUN_CLOCK_ADVANCE + public :: GENERIC_RUN_USER + public :: GENERIC_FINALIZE_USER + enum, bind(c) !!!! IMPORTANT: USER phase must be "1" !!!! enumerator :: GENERIC_INIT_USER = 1 - enumerator :: GENERIC_INIT_CLOCK enumerator :: GENERIC_INIT_GEOM enumerator :: GENERIC_INIT_ADVERTISE enumerator :: GENERIC_INIT_POST_ADVERTISE enumerator :: GENERIC_INIT_REALIZE end enum + enum, bind(c) + enumerator :: GENERIC_RUN_CLOCK_ADVANCE = 1 + enumerator :: GENERIC_RUN_USER + end enum + enum, bind(c) !!!! IMPORTANT: USER phase must be "1" !!!! enumerator :: GENERIC_FINALIZE_USER = 1 end enum integer, parameter :: GENERIC_INIT_PHASE_SEQUENCE(*) = [ & - GENERIC_INIT_CLOCK, & GENERIC_INIT_GEOM, & GENERIC_INIT_ADVERTISE, & GENERIC_INIT_POST_ADVERTISE, & @@ -36,4 +42,5 @@ module mapl3g_GenericPhases GENERIC_INIT_USER & ] + end module mapl3g_GenericPhases diff --git a/generic3g/GriddedComponentDriver.F90 b/generic3g/GriddedComponentDriver.F90 index 4188e5c6c9b8..09a122cd69f3 100644 --- a/generic3g/GriddedComponentDriver.F90 +++ b/generic3g/GriddedComponentDriver.F90 @@ -23,6 +23,7 @@ module mapl3g_GriddedComponentDriver procedure :: run procedure :: initialize procedure :: finalize + procedure :: clock_advance ! Accessors procedure :: get_clock @@ -97,6 +98,11 @@ recursive module subroutine run_import_couplers(this, rc) integer, optional, intent(out) :: rc end subroutine run_import_couplers + module subroutine clock_advance(this, rc) + class(GriddedComponentDriver), intent(inout) :: this + integer, optional, intent(out) :: rc + end subroutine clock_advance + end interface contains diff --git a/generic3g/GriddedComponentDriver_smod.F90 b/generic3g/GriddedComponentDriver_smod.F90 index c2e8e59088a4..cc86c74ba4a5 100644 --- a/generic3g/GriddedComponentDriver_smod.F90 +++ b/generic3g/GriddedComponentDriver_smod.F90 @@ -146,4 +146,15 @@ recursive module subroutine run_export_couplers(this, unusable, phase_idx, rc) _RETURN(_SUCCESS) end subroutine run_export_couplers + module subroutine clock_advance(this, rc) + class(GriddedComponentDriver), intent(inout) :: this + integer, optional, intent(out) :: rc + + integer :: status + + call ESMF_ClockAdvance(this%clock, _RC) + + _RETURN(_SUCCESS) + end subroutine clock_advance + end submodule GriddedComponentDriver_run_smod diff --git a/generic3g/OuterMetaComponent.F90 b/generic3g/OuterMetaComponent.F90 index efc99f98c82e..7b50b5ed4ca9 100644 --- a/generic3g/OuterMetaComponent.F90 +++ b/generic3g/OuterMetaComponent.F90 @@ -82,16 +82,15 @@ module mapl3g_OuterMetaComponent procedure :: init_meta ! object - procedure :: initialize ! init by phase name + procedure :: run_custom procedure :: initialize_user - procedure :: initialize_clock procedure :: initialize_geom procedure :: initialize_advertise procedure :: initialize_post_advertise procedure :: initialize_realize procedure :: run -!# procedure :: run_clock_advance + procedure :: run_clock_advance procedure :: finalize procedure :: read_restart procedure :: write_restart @@ -167,8 +166,11 @@ subroutine I_child_op(this, child_meta, rc) end subroutine I_child_Op end interface + interface recurse + module procedure recurse_ + end interface recurse + interface apply_to_children - module procedure apply_to_children_simple module procedure apply_to_children_custom end interface apply_to_children @@ -351,30 +353,6 @@ end function get_hconfig ! ESMF initialize methods - !------- - ! initialize_geom(): - ! - ! Note that setting the clock is really an operation on component - ! drivers. Thus, the structure here is a bit different than for - ! other initialize phases which act at the component level (and - ! hence the OuterMetaComponent level). - !------- - recursive subroutine initialize_clock(this, clock, unusable, rc) - class(OuterMetaComponent), intent(inout) :: this - ! optional arguments - class(KE), optional, intent(in) :: unusable - type(ESMF_Clock), optional :: clock - integer, optional, intent(out) :: rc - - integer :: status - character(*), parameter :: PHASE_NAME = 'GENERIC::INIT_CLOCK' - - call this%user_gc_driver%set_clock(clock) ! comp _driver_ - call apply_to_children(this, phase_idx=GENERIC_INIT_CLOCK, _RC) - - _RETURN(ESMF_SUCCESS) - - end subroutine initialize_clock !---------- ! The procedure initialize_geom() is responsible for passing grid @@ -385,20 +363,16 @@ end subroutine initialize_clock ! - specifying an INIT_GEOM phase ! If both are specified, the INIT_GEOM overrides the config spec. ! --------- - recursive subroutine initialize_geom(this, clock, unusable, rc) + recursive subroutine initialize_geom(this, unusable, rc) class(OuterMetaComponent), intent(inout) :: this ! optional arguments class(KE), optional, intent(in) :: unusable - type(ESMF_Clock), optional :: clock integer, optional, intent(out) :: rc integer :: status type(MaplGeom), pointer :: mapl_geom character(*), parameter :: PHASE_NAME = 'GENERIC::INIT_GEOM' type(GeomManager), pointer :: geom_mgr - type(StringVector), pointer :: initialize_phases - logical :: found - integer :: phase if (this%component_spec%has_geom_hconfig()) then geom_mgr => get_geom_manager() @@ -406,14 +380,10 @@ recursive subroutine initialize_geom(this, clock, unusable, rc) this%geom = mapl_geom%get_geom() end if - initialize_phases => this%get_phases(ESMF_METHOD_INITIALIZE) - phase = get_phase_index(initialize_phases, PHASE_NAME, found=found) - if (found) then - call this%user_gc_driver%initialize(phase_idx=phase, _RC) - end if + call this%run_custom(ESMF_METHOD_INITIALIZE, PHASE_NAME, _RC) call apply_to_children(this, set_child_geom, _RC) - call apply_to_children(this, phase_idx=GENERIC_INIT_GEOM, _RC) + call recurse(this, phase_idx=GENERIC_INIT_GEOM, _RC) _RETURN(ESMF_SUCCESS) contains @@ -437,28 +407,20 @@ end subroutine set_child_geom end subroutine initialize_geom - recursive subroutine initialize_advertise(this, clock, unusable, rc) + recursive subroutine initialize_advertise(this, unusable, rc) class(OuterMetaComponent), intent(inout) :: this ! optional arguments - type(ESMF_Clock) :: clock class(KE), optional, intent(in) :: unusable integer, optional, intent(out) :: rc integer :: status character(*), parameter :: PHASE_NAME = 'GENERIC::INIT_ADVERTISE' - type(StringVector), pointer :: initialize_phases - logical :: found - integer :: phase - initialize_phases => this%get_phases(ESMF_METHOD_INITIALIZE) - phase = get_phase_index(initialize_phases, PHASE_NAME, found=found) - if (found) then - call this%user_gc_driver%initialize(phase_idx=phase, _RC) - end if + call this%run_custom(ESMF_METHOD_INITIALIZE, PHASE_NAME, _RC) call self_advertise(this, _RC) call apply_to_children(this, add_subregistry, _RC) - call apply_to_children(this, phase_idx=GENERIC_INIT_ADVERTISE, _RC) + call recurse(this, phase_idx=GENERIC_INIT_ADVERTISE, _RC) call process_connections(this, _RC) call this%registry%propagate_unsatisfied_imports(_RC) @@ -564,15 +526,8 @@ recursive subroutine initialize_post_advertise(this, importState, exportState, c integer :: status character(*), parameter :: PHASE_NAME = 'GENERIC::INIT_POST_ADVERTISE' type(MultiState) :: outer_states, user_states - type(StringVector), pointer :: initialize_phases - logical :: found - integer :: phase - initialize_phases => this%get_phases(ESMF_METHOD_INITIALIZE) - phase = get_phase_index(initialize_phases, PHASE_NAME, found=found) - if (found) then - call this%user_gc_driver%initialize(phase_idx=phase, _RC) - end if + call this%run_custom(ESMF_METHOD_INITIALIZE, PHASE_NAME, _RC) user_states = this%user_gc_driver%get_states() call this%registry%add_to_states(user_states, mode='user', _RC) @@ -580,34 +535,24 @@ recursive subroutine initialize_post_advertise(this, importState, exportState, c outer_states = MultiState(importState=importState, exportState=exportState) call this%registry%add_to_states(outer_states, mode='outer', _RC) - call apply_to_children(this, phase_idx=GENERIC_INIT_POST_ADVERTISE, _RC) + call recurse(this, phase_idx=GENERIC_INIT_POST_ADVERTISE, _RC) _RETURN(_SUCCESS) _UNUSED_DUMMY(unusable) end subroutine initialize_post_advertise - - recursive subroutine initialize_realize(this, clock, unusable, rc) + recursive subroutine initialize_realize(this, unusable, rc) class(OuterMetaComponent), intent(inout) :: this ! optional arguments class(KE), optional, intent(in) :: unusable - type(ESMF_Clock), optional :: clock integer, optional, intent(out) :: rc integer :: status character(*), parameter :: PHASE_NAME = 'GENERIC::INIT_REALIZE' - type(StringVector), pointer :: initialize_phases - logical :: found - integer :: phase - - initialize_phases => this%get_phases(ESMF_METHOD_INITIALIZE) - phase = get_phase_index(initialize_phases, PHASE_NAME, found=found) - if (found) then - call this%user_gc_driver%initialize(phase_idx=phase, _RC) - end if - call apply_to_children(this, phase_idx=GENERIC_INIT_REALIZE, _RC) + call this%run_custom(ESMF_METHOD_INITIALIZE, PHASE_NAME, _RC) + call recurse(this, phase_idx=GENERIC_INIT_REALIZE, _RC) call this%registry%allocate(_RC) _RETURN(ESMF_SUCCESS) @@ -616,7 +561,9 @@ recursive subroutine initialize_realize(this, clock, unusable, rc) end subroutine initialize_realize - recursive subroutine apply_to_children_simple(this, phase_idx, rc) + ! This procedure is used to recursively invoke a given ESMF phase down + ! the hierarchy. + recursive subroutine recurse_(this, phase_idx, rc) class(OuterMetaComponent), target, intent(inout) :: this integer :: phase_idx integer, optional, intent(out) :: rc @@ -635,7 +582,7 @@ recursive subroutine apply_to_children_simple(this, phase_idx, rc) end associate _RETURN(_SUCCESS) - end subroutine apply_to_children_simple + end subroutine recurse_ ! This procedure should not be invoked recursively - it is not for traversing the tree, ! but rather just to facilitate custom operations where a parent component must pass @@ -665,73 +612,51 @@ subroutine apply_to_children_custom(this, oper, rc) _RETURN(_SUCCESS) end subroutine apply_to_children_custom - recursive subroutine initialize_user(this, clock, unusable, rc) + recursive subroutine initialize_user(this, unusable, rc) class(OuterMetaComponent), intent(inout) :: this - type(ESMF_Clock) :: clock ! optional arguments class(KE), optional, intent(in) :: unusable integer, optional, intent(out) :: rc integer :: status - character(*), parameter :: PHASE_NAME = 'GENERIC::INIT_USER' - type(StringVector), pointer :: initialize_phases - logical :: found - integer :: phase - initialize_phases => this%get_phases(ESMF_METHOD_INITIALIZE) - phase = get_phase_index(initialize_phases, PHASE_NAME, found=found) - if (found) then - call this%user_gc_driver%initialize(phase_idx=phase, _RC) - end if - - call apply_to_children(this, phase_idx=GENERIC_INIT_USER, _RC) + call this%run_custom(ESMF_METHOD_INITIALIZE, PHASE_NAME, _RC) + call recurse(this, phase_idx=GENERIC_INIT_USER, _RC) _RETURN(ESMF_SUCCESS) _UNUSED_DUMMY(unusable) end subroutine initialize_user - recursive subroutine initialize(this, importState, exportState, clock, unusable, phase_name, rc) + subroutine run_custom(this, method_flag, phase_name, rc) class(OuterMetaComponent), intent(inout) :: this - ! optional arguments - class(KE), optional, intent(in) :: unusable - type(ESMF_State), optional :: importState - type(ESMF_State), optional :: exportState - type(ESMF_Clock), optional :: clock - character(len=*), optional, intent(in) :: phase_name + type(ESMF_METHOD_FLAG), intent(in) :: method_flag + character(*), intent(in) :: phase_name integer, optional, intent(out) :: rc - - integer :: status, userRC - type(StringVector), pointer :: initialize_phases + + integer :: status + integer :: phase_idx + type(StringVector), pointer :: phases logical :: found - integer :: phase - - _ASSERT(present(phase_name),'phase_name is mandatory') - - select case (phase_name) - case ('GENERIC::INIT_GEOM') - call this%initialize_geom(clock, _RC) - case ('GENERIC::INIT_ADVERTISE') - call this%initialize_advertise(clock, _RC) - case ('GENERIC::INIT_USER') - call this%initialize_user(clock, _RC) - case default ! custom user phase - does not auto propagate to children - - initialize_phases => this%get_phases(ESMF_METHOD_INITIALIZE) - phase = get_phase_index(initialize_phases, PHASE_NAME, found=found) - if (found) then - call this%user_gc_driver%initialize(phase_idx=phase, _RC) - end if - end select - - _RETURN(ESMF_SUCCESS) - end subroutine initialize + phases => this%get_phases(method_flag) + phase_idx = get_phase_index(phases, phase_name, found=found) + _RETURN_UNLESS(found) + if (method_flag == ESMF_METHOD_INITIALIZE) then + call this%user_gc_driver%initialize(phase_idx=phase_idx, _RC) + else if (method_flag == ESMF_METHOD_RUN) then + call this%user_gc_driver%run(phase_idx=phase_idx, _RC) + else if (method_flag == ESMF_METHOD_FINALIZE) then + call this%user_gc_driver%finalize(phase_idx=phase_idx, _RC) + else + _FAIL('Unknown ESMF method flag.') + end if + _RETURN(_SUCCESS) + end subroutine run_custom - recursive subroutine run(this, clock, phase_name, unusable, rc) + recursive subroutine run(this, phase_name, unusable, rc) class(OuterMetaComponent), target, intent(inout) :: this - type(ESMF_Clock) :: clock ! optional arguments character(len=*), optional, intent(in) :: phase_name class(KE), optional, intent(in) :: unusable @@ -749,6 +674,12 @@ recursive subroutine run(this, clock, phase_name, unusable, rc) type(ActualPtComponentDriverMapIterator) :: iter type(GriddedComponentDriver), pointer :: drvr + select case (phase_name) + case ('GENERIC::RUN_CLOCK_ADVANCE') + call this%run_clock_advance(_RC) + _RETURN(_SUCCESS) + end select + run_phases => this%get_phases(ESMF_METHOD_RUN) phase = get_phase_index(run_phases, phase_name, found=found) _RETURN_UNLESS(found) @@ -793,26 +724,29 @@ end subroutine run ! (alarm is ringing) -!# recursive subroutine run_clock_advance(this, clock, unusable, rc) -!# class(OuterMetaComponent), intent(inout) :: this -!# type(ESMF_Clock) :: clock -!# ! optional arguments -!# class(KE), optional, intent(in) :: unusable -!# integer, optional, intent(out) :: rc -!# -!# integer :: status, userRC, i -!# integer :: phase_idx -!# type(StateExtension), pointer :: extension -!# type(StringVector), pointer :: run_phases -!# logical :: found -!# integer :: phase -!# -!# if (found) then -!# call this%user_gc_driver%clock_advance(_RC) -!# end if -!# -!# _RETURN(ESMF_SUCCESS) -!# end subroutine run_clock_advance + recursive subroutine run_clock_advance(this, unusable, rc) + class(OuterMetaComponent), intent(inout) :: this + ! optional arguments + class(KE), optional, intent(in) :: unusable + integer, optional, intent(out) :: rc + + integer :: status + type(GriddedComponentDriverMapIterator) :: iter + type(GriddedComponentDriver), pointer :: child + + associate(e => this%children%ftn_end()) + iter = this%children%ftn_begin() + do while (iter /= e) + call iter%next() + child => iter%second() + call child%run(phase_idx=GENERIC_RUN_CLOCK_ADVANCE, _RC) + end do + end associate + + call this%user_gc_driver%clock_advance(_RC) + + _RETURN(ESMF_SUCCESS) + end subroutine run_clock_advance recursive subroutine finalize(this, importState, exportState, clock, unusable, rc) class(OuterMetaComponent), intent(inout) :: this @@ -840,7 +774,7 @@ recursive subroutine finalize(this, importState, exportState, clock, unusable, r ! TODO: Should there be a phase option here? Probably not ! right as is when things get more complicated. - call this%user_gc_driver%finalize(_RC) + call this%run_custom(ESMF_METHOD_FINALIZE, PHASE_NAME, _RC) associate(b => this%children%begin(), e => this%children%end()) iter = b diff --git a/generic3g/OuterMetaComponent_smod.F90 b/generic3g/OuterMetaComponent_smod.F90 index 1c7ec42f593d..2db1f452ddd7 100644 --- a/generic3g/OuterMetaComponent_smod.F90 +++ b/generic3g/OuterMetaComponent_smod.F90 @@ -113,15 +113,16 @@ module recursive subroutine add_child_by_name(this, child_name, setservices, hco integer :: status type(GriddedComponentDriver) :: child_gc_driver type(ESMF_GridComp) :: child_gc - type(ESMF_Clock) :: clock + type(ESMF_Clock) :: clock, child_clock _ASSERT(is_valid_name(child_name), 'Child name <' // child_name //'> does not conform to GEOS standards.') clock = this%user_gc_driver%get_clock() + child_clock = ESMF_ClockCreate(clock, _RC) child_gc = create_grid_comp(child_name, setservices, hconfig, clock, _RC) call ESMF_GridCompSetServices(child_gc, generic_setservices, _RC) - child_gc_driver = GriddedComponentDriver(child_gc, clock, MultiState()) + child_gc_driver = GriddedComponentDriver(child_gc, child_clock, MultiState()) _ASSERT(this%children%count(child_name) == 0, 'duplicate child name: <'//child_name//'>.') call this%children%insert(child_name, child_gc_driver) diff --git a/generic3g/tests/Test_RunChild.pf b/generic3g/tests/Test_RunChild.pf index 48969aef5b84..8a1b35802e1f 100644 --- a/generic3g/tests/Test_RunChild.pf +++ b/generic3g/tests/Test_RunChild.pf @@ -120,7 +120,7 @@ contains call setup(this, rc=status) @assert_that(status, is(0)) - call parent_meta%initialize_user(clock, rc=status) + call parent_meta%initialize_user(rc=status) @assert_that(status, is(0)) @assertEqual("wasInit :: wasInit_child_1 :: wasInit_child_2", log)