CMake netCDF Compatibility with WPS (#2121)
[WRF.git] / frame / module_integrate.F
blob4aec5aae0bcef844ca6588af7e048ed056359e1f
1 !WRF:DRIVER_LAYER:INTEGRATION
4 MODULE module_integrate
6 CONTAINS
8 RECURSIVE SUBROUTINE integrate ( grid )
12    USE module_domain
13    USE module_driver_constants
14    USE module_nesting
15    USE module_configure
16    USE module_timing
17    USE module_utility
18 #if ( WRFPLUS == 1 )
19 !   USE module_linked_list2, only : linkedlist_initialize
20 #endif
21    USE module_cpl, ONLY : coupler_on, cpl_snd, cpl_defdomain
22 #ifdef DM_PARALLEL
23 ! better if this did not need to be used here. Problem is that the definition of 
24 ! domain_active_this_task comes from module_dm, and the routine it's being passed to (alloc_and_configure_domain)
25 ! is defined in module_domain, which uses module_dm.  If that weren't the case, we could have the
26 ! alloc_and_configure_domain routine get this form the module_dm module itself, but as it stands there
27 ! would be a circular use association.  jm 20140828
28    USE module_dm, ONLY:  domain_active_this_task !, push_communicators_for_domain, pop_communicators_for_domain
29 #endif
31    IMPLICIT NONE
33    !  Input data.
35    TYPE(domain) , POINTER :: grid
37 ! module_integrate:integrate
38 ! <DESCRIPTION> 
39 ! This is a driver-level routine that controls the integration of a
40 ! domain and subdomains rooted at the domain. 
41
42 ! The integrate routine takes a domain pointed to by the argument
43 ! <em>grid</em> and advances the domain and its associated nests from the
44 ! grid's current time, stored within grid%domain_clock, to a given time
45 ! forward in the simulation, stored as grid%stop_subtime. The
46 ! stop_subtime value is arbitrary and does not have to be the same as
47 ! time that the domain finished integrating.  The simulation stop time
48 ! for the grid is known to the grid's clock (grid%domain_clock) and that
49 ! is checked with a call to domain_clockisstoptime prior to beginning the
50 ! loop over time period that is specified by the
51 ! current time/stop_subtime interval.
52
53 ! The clock, the simulation stop time for the domain, and other timing
54 ! aspects for the grid are set up in the routine
55 ! (<a href="setup_timekeeping.html">setup_timekeeping</a>) at the time
56 ! that the domain is initialized.
57 ! The lower-level time library and the type declarations for the times
58 ! and time intervals used are defined either in 
59 ! external/esmf_time_f90/module_utility.F90 or in 
60 ! external/io_esmf/module_utility.F90 depending on a build-time decision to 
61 ! incorporate either the embedded ESMF subset implementation contained in 
62 ! external/esmf_time_f90 or to use a site-specific installation of the ESMF 
63 ! library.  This decision is made during the configuration step of the WRF 
64 ! build process.  Note that arithmetic and comparison is performed on these 
65 ! data types using F90 operator overloading, also defined in that library.
66
67 ! This routine is the lowest level of the WRF Driver Layer and for the most
68 ! part the WRF routines that are called from here are in the topmost level
69 ! of the Mediation Layer.  Mediation layer routines typically are not 
70 ! defined in modules. Therefore, the routines that this routine calls
71 ! have explicit interfaces specified in an interface block in this routine.
73 ! As part of the Driver Layer, this routine is intended to be non model-specific
74 ! and so a minimum of WRF-specific logic is coded at this level. Rather, there
75 ! are a number of calls to mediation layer routines that contain this logic, some
76 ! of which are merely stubs in WRF Mediation Layer that sits below this routine
77 ! in the call tree.  The routines that integrate calls in WRF are defined in
78 ! share/mediation_integrate.F.
79
80 ! Flow of control
81
82 ! 1. Check to see that the domain is not finished 
83 ! by testing the value returned by domain_clockisstoptime for the
84 ! domain.
85
86 ! 2. <a href=model_to_grid_config_rec.html>Model_to_grid_config_rec</a> is called to load the local config_flags
87 ! structure with the configuration information for the grid stored
88 ! in model_config_rec and indexed by the grid's unique integer id. These
89 ! structures are defined in frame/module_configure.F.
90
91 ! 3. The current time of the domain is retrieved from the domain's clock
92 ! using domain_get_current_time.  
93
94 ! 4. Iterate forward while the current time is less than the stop subtime.
95
96 ! 4.a. Start timing for this iteration (only on node zero in distributed-memory runs)
97
98 ! 4.b. Call <a href=med_setup_step.html>med_setup_step</a> to allow the mediation layer to 
99 ! do anything that's needed to call the solver for this domain.  In WRF this means setting
100 ! the indices into the 4D tracer arrays for the domain.
102 ! 4.c. Check for any nests that need to be started up at this time.  This is done 
103 ! calling the logical function <a href=nests_to_open.html>nests_to_open</a> (defined in 
104 ! frame/module_nesting.F) which returns true and the index into the current domain's list
105 ! of children to use for the nest when one needs to be started.
107 ! 4.c.1  Call <a href=alloc_and_configure_domain.html>alloc_and_configure_domain</a> to allocate
108 ! the new nest and link it as a child of this grid.
110 ! 4.c.2  Call <a href=setup_Timekeeping.html>setup_Timekeeping</a> for the nest.
112 ! 4.c.3  Initialize the nest's arrays by calling <a href=med_nest_initial.html>med_nest_initial</a>. This will
113 ! either interpolate data from this grid onto the nest, read it in from a file, or both. In a restart run, this
114 ! is also where the nest reads in its restart file.
116 ! 4.d  If a nest was opened above, check for and resolve overlaps (this is not implemented in WRF 2.0, which
117 ! supports multiple nests on the same level but does not support overlapping).
119 ! 4.e  Give the mediation layer an opportunity to do something before the solver is called by
120 ! calling <a href=med_before_solve_io.html>med_before_solve_io</a>. In WRF this is the point at which history and
121 ! restart data is output.
123 ! 4.f  Call <a href=solve_interface.html>solve_interface</a> which calls the solver that advance the domain 
124 ! one time step, then advance the domain's clock by calling domain_clockadvance.  
125 ! The enclosing WHILE loop around this section is for handling other domains 
126 ! with which this domain may overlap.  It is not active in WRF 2.0 and only 
127 ! executes one trip.  
129 ! 4.g Call med_calc_model_time and med_after_solve_io, which are stubs in WRF.
131 ! 4.h Iterate over the children of this domain (<tt>DO kid = 1, max_nests</tt>) and check each child pointer to see
132 ! if it is associated (and therefore, active).
134 ! 4.h.1  Force the nested domain boundaries from this domain by calling <a href=med_nest_force.html>med_nest_force</a>.
136 ! 4.h.2  Setup the time period over which the nest is to run. Sine the current grid has been advanced one time step
137 ! and the nest has not, the start for the nest is this grid's current time minus one time step.  The nest's stop_subtime
138 ! is the current time, bringing the nest up the same time level as this grid, its parent.
140 ! 4.h.3  Recursively call this routine, integrate, to advance the nest's time.  Since it is recursive, this will
141 ! also advance all the domains who are nests of this nest and so on.  In other words, when this call returns, all
142 ! the domains rooted at the nest will be at the current time.
144 ! 4.h.4  Feedback data from the nested domain back onto this domain by calling <a href=med_nest_feedback.html>med_nest_feedback</a>.
146 ! 4.i  Write the time to compute this grid and its subtree. This marks the end of the loop begun at step 4, above.
148 ! 5. Give the mediation layer an opportunity to do I/O at the end of the sequence of steps that brought the
149 ! grid up to stop_subtime with a call to <a href=med_last_solve_io.html>med_last_solve_io</a>.  In WRF, this 
150 ! is used to generate the final history and/or restart output when the domain reaches the end of it's integration.
151 ! There is logic here to make sure this occurs correctly on a nest, since the nest may finish before its parent.
152 ! </DESCRIPTION>
154    !  Local data.
156    CHARACTER*32                           :: outname, rstname
157    TYPE(domain) , POINTER                 :: grid_ptr , new_nest
158    TYPE(domain)                           :: intermediate_grid
159    INTEGER                                :: step
160    INTEGER                                :: nestid , kid
161    LOGICAL                                :: a_nest_was_opened
162    INTEGER                                :: fid , rid
163    LOGICAL                                :: lbc_opened
164    REAL                                   :: time, btime, bfrq
165    CHARACTER*256                          :: message, message2,message3
166    TYPE (grid_config_rec_type)            :: config_flags
167    LOGICAL , EXTERNAL                     :: wrf_dm_on_monitor
168    INTEGER                                :: idum1 , idum2 , ierr , open_status
169    LOGICAL                                :: should_do_last_io
170    LOGICAL                                :: may_have_moved
171 #if ( WRFPLUS == 1 )
172    INTEGER                                :: rc
173    LOGICAL                                :: should_add_forcing
174 #endif
176    ! interface
177    INTERFACE
178        ! mediation-supplied solver
179      SUBROUTINE solve_interface ( grid )
180        USE module_domain
181        TYPE (domain) grid
182      END SUBROUTINE solve_interface
183        ! mediation-supplied routine to allow driver to pass time information
184        ! down to mediation/model layer
185      SUBROUTINE med_calc_model_time ( grid , config_flags )
186        USE module_domain
187        USE module_configure
188        TYPE (domain) grid
189        TYPE (grid_config_rec_type) config_flags
190      END SUBROUTINE med_calc_model_time
191        ! mediation-supplied routine that gives mediation layer opportunity to 
192        ! perform I/O before the call to the solve routine
193      SUBROUTINE med_before_solve_io ( grid , config_flags )
194        USE module_domain
195        USE module_configure
196        TYPE (domain) grid
197        TYPE (grid_config_rec_type) config_flags
198      END SUBROUTINE med_before_solve_io
199 #if ( WRFPLUS == 1 )
200      SUBROUTINE med_last_ad_solve_io ( grid , config_flags )
201        USE module_domain
202        USE module_configure
203        TYPE (domain) grid
204        TYPE (grid_config_rec_type) config_flags
205      END SUBROUTINE med_last_ad_solve_io
206      SUBROUTINE jcdfi_init_coef
207      END SUBROUTINE jcdfi_init_coef
208      SUBROUTINE jcdfi_zero_forcing ( grid )
209        USE module_domain
210        TYPE (domain) grid
211      END SUBROUTINE jcdfi_zero_forcing
212      SUBROUTINE jcdfi_tl ( grid )
213        USE module_domain
214        TYPE (domain) grid
215      END SUBROUTINE jcdfi_tl
216      SUBROUTINE jcdfi_add_forcing (grid)
217        USE module_domain
218        TYPE (domain) grid
219      END SUBROUTINE jcdfi_add_forcing
220 #endif
221        ! mediation-supplied routine that gives mediation layer opportunity to 
222        ! perform I/O after the call to the solve routine
223      SUBROUTINE med_after_solve_io ( grid , config_flags )
224        USE module_domain
225        USE module_configure
226        TYPE (domain) grid
227        TYPE (grid_config_rec_type) config_flags
228      END SUBROUTINE med_after_solve_io
229        ! mediation-supplied routine that gives mediation layer opportunity to 
230        ! perform I/O to initialize a new nest
231      SUBROUTINE med_pre_nest_initial ( parent , newid , config_flags )
232        USE module_domain
233        USE module_configure
234        TYPE (domain), POINTER ::  parent
235        INTEGER, INTENT(IN)    ::  newid
236        TYPE (grid_config_rec_type) config_flags
237      END SUBROUTINE med_pre_nest_initial
238      SUBROUTINE med_nest_initial ( parent , grid , config_flags )
239        USE module_domain
240        USE module_configure
241        TYPE (domain), POINTER ::  grid , parent
242        TYPE (grid_config_rec_type) config_flags
243      END SUBROUTINE med_nest_initial
244        ! mediation-supplied routine that gives mediation layer opportunity to 
245        ! provide parent->nest forcing
246      SUBROUTINE med_nest_force ( parent , grid )
247        USE module_domain
248        USE module_configure
249        TYPE (domain), POINTER ::  grid, parent
250      END SUBROUTINE med_nest_force
252 #ifdef MOVE_NESTS
253      SUBROUTINE med_nest_move ( parent , grid )
254        USE module_domain
255        USE module_configure
256        TYPE (domain), POINTER ::  grid , parent
257      END SUBROUTINE med_nest_move
258      SUBROUTINE reconcile_nest_positions_over_tasks ( grid )
259        USE module_domain
260        USE module_configure
261        TYPE (domain), POINTER ::  grid
262      END SUBROUTINE reconcile_nest_positions_over_tasks
263 #endif
265        ! mediation-supplied routine that gives mediation layer opportunity to 
266        ! provide parent->nest feedback
267      SUBROUTINE med_nest_feedback ( parent , grid , config_flags )
268        USE module_domain
269        USE module_configure
270        TYPE (domain), POINTER ::  grid , parent
271        TYPE (grid_config_rec_type) config_flags
272      END SUBROUTINE med_nest_feedback
274        ! mediation-supplied routine that gives mediation layer opportunity to 
275        ! perform I/O prior to the close of this call to integrate
276      SUBROUTINE med_last_solve_io ( grid , config_flags )
277        USE module_domain
278        USE module_configure
279        TYPE (domain) grid
280        TYPE (grid_config_rec_type) config_flags
281      END SUBROUTINE med_last_solve_io
282        ! mediation-supplied routine that gives mediation layer opportunity to 
283        ! perform setup before iteration over steps in this call to integrate
284      SUBROUTINE med_setup_step ( grid , config_flags )
285        USE module_domain
286        USE module_configure
287        TYPE (domain) grid
288        TYPE (grid_config_rec_type) config_flags
289      END SUBROUTINE med_setup_step
290        ! mediation-supplied routine that gives mediation layer opportunity to
291        ! perform setup before iteration over steps in this call to integrate
292      SUBROUTINE med_endup_step ( grid , config_flags )
293        USE module_domain
294        USE module_configure
295        TYPE (domain) grid
296        TYPE (grid_config_rec_type) config_flags
297      END SUBROUTINE med_endup_step
298        ! mediation-supplied routine that intializes the nest from the grid
299        ! by interpolation
301      SUBROUTINE Setup_Timekeeping( grid )
302        USE module_domain
303        TYPE(domain), POINTER :: grid
304      END SUBROUTINE
306      SUBROUTINE dfi_accumulate( grid )
307        USE module_domain
308        TYPE(domain), POINTER :: grid
309      END SUBROUTINE
311    END INTERFACE
313    ! This allows us to reference the current grid from anywhere beneath 
314    ! this point for debugging purposes.  
315    CALL set_current_grid_ptr( grid )
316    CALL push_communicators_for_domain( grid%id )
318    IF ( .NOT. domain_clockisstoptime( grid ) ) THEN
319       CALL model_to_grid_config_rec ( grid%id , model_config_rec , config_flags )
320       IF ( config_flags%grid_allowed ) THEN
321          CALL domain_clockprint ( 150, grid, 'DEBUG:  top of integrate(),' )
322 #if ( WRFPLUS == 1 )
323          IF ( (grid%jcdfi_use .OR. grid%jcdfi_diag .EQ. 1) .AND. config_flags%dyn_opt .EQ. dyn_em_tl ) THEN
324             CALL jcdfi_zero_forcing (grid)
325             CALL jcdfi_tl (grid)
326          ENDIF
327 #endif
328          DO WHILE ( .NOT. domain_clockisstopsubtime(grid) )
329             IF ( wrf_dm_on_monitor() ) THEN
330 IF ( grid%active_this_task ) THEN
331                CALL start_timing
332 END IF
333             END IF
334             CALL med_setup_step ( grid , config_flags )
335             a_nest_was_opened = .false.
336             ! for each nest whose time has come...
337             DO WHILE ( nests_to_open( grid , nestid , kid ) )
338                ! nestid is index into model_config_rec (module_configure) of the grid
339                ! to be opened; kid is index into an open slot in grid's list of children
340                a_nest_was_opened = .true.
341                CALL med_pre_nest_initial ( grid , nestid , config_flags )
342                CALL alloc_and_configure_domain ( domain_id  = nestid ,   &
343 ! better if this were not ifdef'd here, try moving into module_dm? see comment above. jm 20140828
344 #ifdef DM_PARALLEL
345                                            active_this_task = domain_active_this_task( nestid ), &
346 #endif
347                                                  grid       = new_nest , &
348                                                  parent     = grid ,     &
349                                                  kid        = kid        )
350                CALL Setup_Timekeeping (new_nest)
351                CALL med_nest_initial ( grid , new_nest , config_flags )
352 IF ( grid%active_this_task ) THEN
353                IF ( grid%dfi_stage == DFI_STARTFWD ) THEN
354                   CALL wrf_dfi_startfwd_init(new_nest)
355                ENDIF
356                IF (coupler_on) CALL cpl_defdomain( new_nest ) 
357 ENDIF ! active_this_task
358             END DO
359             IF ( a_nest_was_opened ) THEN
360                CALL set_overlaps ( grid )   ! find overlapping and set pointers
361             END IF
363 IF ( grid%active_this_task ) THEN
364             ! Accumulation calculation for DFI
365               CALL dfi_accumulate ( grid )
366 ENDIF ! active_this_task
368 #if ( WRFPLUS == 1 )
369             ! Check if the auxinput3 is ringing before read it
370             should_add_forcing = .FALSE.
371             IF ( WRFU_AlarmIsRinging( grid%alarms( AUXINPUT7_ALARM ), rc=rc ) ) should_add_forcing = .TRUE.  
372 #endif
374 IF ( grid%active_this_task ) THEN
375               CALL med_before_solve_io ( grid , config_flags )
376 ENDIF ! active_this_task
378 #if ( WRFPLUS == 1 )
379             IF ( config_flags%dyn_opt .EQ. dyn_em_ad .AND. should_add_forcing) THEN
380               CALL add_forcing_to_ad ( grid )
381             ENDIF
382             IF ( grid%jcdfi_use .AND. config_flags%dyn_opt .EQ. dyn_em_ad ) THEN
383                CALL jcdfi_add_forcing ( grid )
384             ENDIF
385 #endif
387             grid_ptr => grid
388             DO WHILE ( ASSOCIATED( grid_ptr ) )
389 IF ( grid_ptr%active_this_task ) THEN
390                   CALL set_current_grid_ptr( grid_ptr )
391                   CALL wrf_debug( 100 , 'module_integrate: calling solve interface ' )
393                   CALL solve_interface ( grid_ptr ) 
395 ENDIF
396                CALL domain_clockadvance ( grid_ptr )
397                CALL wrf_debug( 100 , 'module_integrate: back from solve interface ' )
398                ! print lots of time-related information for testing
399                ! switch this on with namelist variable self_test_domain
400                CALL domain_time_test( grid_ptr, 'domain_clockadvance' )
401                grid_ptr => grid_ptr%sibling
402             END DO
403             CALL set_current_grid_ptr( grid )
404             CALL med_calc_model_time ( grid , config_flags )
405 IF ( grid%active_this_task ) THEN
406               CALL med_after_solve_io ( grid , config_flags )
407 ENDIF
409             grid_ptr => grid
410             DO WHILE ( ASSOCIATED( grid_ptr ) )
411                DO kid = 1, max_nests
412                  IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
413                    CALL set_current_grid_ptr( grid_ptr%nests(kid)%ptr )
414                    ! Recursive -- advance nests from previous time level to this time level.
415                    CALL wrf_debug( 100 , 'module_integrate: calling med_nest_force ' )
416                    CALL med_nest_force ( grid_ptr , grid_ptr%nests(kid)%ptr )
417                    CALL wrf_debug( 100 , 'module_integrate: back from med_nest_force ' )
418                    grid_ptr%nests(kid)%ptr%start_subtime = &
419                      domain_get_current_time(grid) - domain_get_time_step(grid)
420                    grid_ptr%nests(kid)%ptr%stop_subtime = &
421                      domain_get_current_time(grid)
422                  ENDIF
423                ENDDO
425                DO kid = 1, max_nests
426                  IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
427                    CALL set_current_grid_ptr( grid_ptr%nests(kid)%ptr )
428                    WRITE(message,*)grid%id,' module_integrate: recursive call to integrate '
429                    CALL wrf_debug( 100 , message )
430                       CALL integrate ( grid_ptr%nests(kid)%ptr ) 
431                    WRITE(message,*)grid%id,' module_integrate: back from recursive call to integrate '
432                    CALL wrf_debug( 100 , message )
433                  ENDIF
434                ENDDO
435                may_have_moved = .FALSE.
436                DO kid = 1, max_nests
437                  IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
438                    CALL set_current_grid_ptr( grid_ptr%nests(kid)%ptr )
439                    IF ( .NOT. ( domain_clockisstoptime(head_grid              ) .OR. &
440                                 domain_clockisstoptime(grid                   ) .OR. &
441                                 domain_clockisstoptime(grid_ptr%nests(kid)%ptr) ) )  THEN
442                      CALL wrf_debug( 100 , 'module_integrate: calling med_nest_feedback ' )
443                      CALL med_nest_feedback ( grid_ptr , grid_ptr%nests(kid)%ptr , config_flags )
444                      CALL wrf_debug( 100 , 'module_integrate: back from med_nest_feedback ' )
445                    END IF
446 #ifdef MOVE_NESTS
447                    IF ( .NOT. domain_clockisstoptime( head_grid ) ) THEN
448                      CALL med_nest_move ( grid_ptr , grid_ptr%nests(kid)%ptr )
449                      may_have_moved = .TRUE.
450                    ENDIF
451 #endif
452                  END IF
453                END DO
454 #ifdef MOVE_NESTS
455                IF ( may_have_moved ) THEN
456                  CALL reconcile_nest_positions_over_tasks( grid_ptr )
457                  CALL model_to_grid_config_rec ( grid_ptr%id , model_config_rec , config_flags )
458                ENDIF
459 #endif
460                IF (coupler_on) CALL cpl_snd( grid_ptr ) 
461                grid_ptr => grid_ptr%sibling
462             END DO
463             CALL set_current_grid_ptr( grid )
464             !  Report on the timing for a single time step.
465             IF ( wrf_dm_on_monitor() ) THEN
466 IF ( grid%active_this_task ) THEN
467                CALL domain_clock_get ( grid, current_timestr=message2 )
468 #if (EM_CORE == 1)
469                if (config_flags%use_adaptive_time_step) then
470                   WRITE ( message , FMT = '("main (dt=",F6.2,"): time ",A," on domain ",I3)' ) grid%dt, TRIM(message2), grid%id
471                else
472                   WRITE ( message , FMT = '("main: time ",A," on domain ",I3)' ) TRIM(message2), grid%id
473                endif
474 #else
475                   WRITE ( message , FMT = '("main: time ",A," on domain ",I3)' ) TRIM(message2), grid%id
476 #endif
477                CALL end_timing ( TRIM(message) )
478 ENDIF ! active_this_task
479             ENDIF
480 #if ( WRFPLUS == 1 )
481             IF ( (grid%jcdfi_use .OR. grid%jcdfi_diag .EQ. 1) .AND. config_flags%dyn_opt .EQ. dyn_em_tl ) THEN
482                CALL jcdfi_tl (grid)
483             ENDIF
484 #endif
485             CALL med_endup_step ( grid , config_flags )
486          END DO
488 IF ( grid%active_this_task ) THEN
489          ! Accumulation calculation for DFI
490          CALL dfi_accumulate ( grid )
491 ENDIF ! active_this_task
493 #if ( WRFPLUS == 1 )
494 !        Read in first basic states and forcing, add forcing
495          IF ( config_flags%dyn_opt .EQ. dyn_em_ad .AND. WRFU_AlarmIsRinging( grid%alarms( AUXINPUT7_ALARM ), rc=rc ) ) THEN
496            CALL med_last_ad_solve_io ( grid , config_flags )
497            CALL add_forcing_to_ad ( grid )
498          ENDIF
499          IF ( grid%jcdfi_use .AND. config_flags%dyn_opt .EQ. dyn_em_ad ) THEN
500             CALL jcdfi_add_forcing ( grid )
501          ENDIF
502          !IF ( config_flags%dyn_opt .EQ. dyn_em_ad ) THEN
503          !   CALL linkedlist_initialize
504          !ENDIF
505 #endif
507          ! Avoid double writes on nests if this is not really the last time;
508          ! Do check for write if the parent domain is ending.
509          IF ( grid%id .EQ. 1 ) THEN               ! head_grid
510             IF ( grid%active_this_task ) CALL med_last_solve_io ( grid , config_flags )
511          ELSE
512 ! zip up the tree and see if any ancestor is at its stop time
513             should_do_last_io = domain_clockisstoptime( head_grid )
514             grid_ptr => grid 
515             DO WHILE ( grid_ptr%id .NE. 1 )
516                IF ( domain_clockisstoptime( grid_ptr ) ) THEN
517                   should_do_last_io = .TRUE. 
518                END IF
519                grid_ptr => grid_ptr%parents(1)%ptr
520             ENDDO
521             IF ( should_do_last_io ) THEN 
522                grid_ptr => grid 
523                CALL med_nest_feedback ( grid_ptr%parents(1)%ptr, grid , config_flags )
524                IF ( grid%active_this_task ) CALL med_last_solve_io ( grid , config_flags )
525             ENDIF
526          ENDIF
527       ENDIF
528    END IF
529    CALL pop_communicators_for_domain
530    
531 END SUBROUTINE integrate
533 END MODULE module_integrate