prismdrv_init_appl.F90

Go to the documentation of this file.
00001 !------------------------------------------------------------------------
00002 ! Copyright 2006-2010, CERFACS, Toulouse, France.
00003 ! All rights reserved. Use is subject to OASIS4 license terms.
00004 !-----------------------------------------------------------------------
00005 !BOP
00006 !
00007 ! !ROUTINE: PRISMDrv_Init_appl
00008 !
00009 ! !INTERFACE
00010 subroutine prismdrv_init_appl(id_err)
00011 
00012 !
00013 ! !USES:
00014 !
00015   USE PRISMDrv, dummy_interface => PRISMDrv_Init_appl
00016   use psmile_timer, only : psmile_timer_init, psmile_timer_start
00017 
00018   IMPLICIT NONE
00019 
00020 !
00021 ! !PARAMETERS:
00022 !
00023 
00024 !
00025 ! ! RETURN VALUE
00026 !
00027   INTEGER, INTENT (Out)               :: id_err   ! error value
00028 
00029 ! !DESCRIPTION
00030 ! Subroutine "PRISMDrv_Init_appl" sets the computational context of the 
00031 ! different applications in MPI1 such as the communicators, and spawn 
00032 ! these applications in MPI2 and set the context.
00033 !
00034 ! !REVISED HISTORY
00035 !   Date      Programmer   Description
00036 ! ----------  ----------   -----------
00037 ! 04/10/2002  D. Declat    Creation
00038 !
00039 ! EOP
00040 !----------------------------------------------------------------------
00041 ! $Id: prismdrv_init_appl.F90 2846 2011-01-04 12:02:30Z hanke $
00042 ! $Author: hanke $
00043 !----------------------------------------------------------------------
00044 !
00045 ! 0. Local declarations
00046 !
00047   CHARACTER(LEN=len_cvs_string), SAVE  :: mycvs = 
00048      '$Id: prismdrv_init_appl.F90 2846 2011-01-04 12:02:30Z hanke $'
00049 
00050   INTEGER :: il_size, il_status(MPI_STATUS_SIZE)
00051   INTEGER :: il_inter   ! inter comm obtained by mpi_comm_spawn 
00052 
00053 !    When an application is spawned, some info are sent via a buffer 
00054 !    dimensionned by il_dim_buf. These info are the protocol version
00055 !    the number of applications and the last current application spawned
00056   INTEGER :: il_dim_buf
00057   INTEGER, DIMENSION(:), ALLOCATABLE :: ila_buf
00058   INTEGER :: il_protocol_version
00059 
00060   INTEGER :: ib, ib_bis, ib_ter, ib_quad
00061   INTEGER :: il_comp_index  
00062 
00063   INTEGER :: n_host ! pointer to hostlist for current application
00064   INTEGER :: n_args ! pointer to arguemt list for current application
00065 
00066   LOGICAL :: ll_flag
00067 
00068   INTEGER, PARAMETER                  :: nerrp=3
00069   INTEGER                             :: ierrp(nerrp)
00070 !
00071   INTEGER, DIMENSION(15) :: ila_date
00072   DOUBLE PRECISION, DIMENSION(3) :: dla_date
00073 
00074 #ifdef PROFILE
00075   CHARACTER (LEN=max_name) :: timer_label(1)
00076 #endif
00077 !
00078 !----------------------------------------------------------------------
00079 !
00080 #ifdef VERBOSE
00081   PRINT *, '| Enter PRISMDrv_Init_appl'
00082   call psmile_flushstd
00083 #endif
00084 !
00085 ! 1. Process management if MPI1 or MPI2 and not spawn
00086 !
00087   IF (ig_MPI .eq. DRV_MPI1) THEN
00088 
00089 #ifdef VERBOSE
00090       PRINT *, '| | MPI1 implementation'
00091       call psmile_flushstd
00092 #endif
00093 ! 1.1. Duplicate MPI_COMM_WORLD to create the global communicator
00094 
00095       CALL MPI_Comm_dup (MPI_COMM_WORLD, comm_drv_global, id_err)
00096 
00097       IF ( id_err /= MPI_SUCCESS ) THEN
00098           ierrp (1) = id_err
00099           id_err = PRISM_Error_MPI
00100 
00101           call psmile_error_common ( id_err, 'MPI_Comm_dup', &
00102              ierrp, 1, __FILE__, __LINE__ )
00103           RETURN
00104       ENDIF
00105 
00106 !
00107 ! 1.1. Duplicate the global communicator to Get the transformer comm
00108 !
00109       CALL MPI_Comm_dup (comm_drv_global, comm_drv_trans, id_err)
00110 
00111       IF ( id_err /= MPI_SUCCESS ) THEN
00112           ierrp (1) = id_err
00113           id_err = PRISM_Error_MPI
00114 
00115           call psmile_error_common ( id_err, 'MPI_Comm_dup', &
00116              ierrp, 1, __FILE__, __LINE__ )
00117           RETURN
00118       ENDIF
00119 
00120 !
00121 ! 1.2. Manage the exchange of information between the driver the 
00122 !      transformer and the appl.
00123 !
00124 ! 1.2.1. Get protocol version for communication between the coupler
00125 !          and the models (applications)
00126       CALL MPI_Allreduce (DRV_latest_protocol_version, &
00127          il_protocol_version, 1, MPI_Integer, MPI_MIN, &
00128          comm_drv_global, id_err)
00129 
00130       IF ( id_err /= MPI_SUCCESS ) THEN
00131           ierrp (1) = id_err
00132           id_err = PRISM_Error_MPI
00133 
00134           call psmile_error_common ( id_err, 'MPI_Allreduce', &
00135              ierrp, 1, __FILE__, __LINE__ )
00136           RETURN
00137       ENDIF
00138 
00139       IF (  il_protocol_version < DRV_latest_protocol_version) THEN
00140 
00141          PRINT *, '| | Protocol versions differ.'
00142          PRINT *, '| | PSMILE protocol version is ', il_protocol_version
00143          PRINT *, '| | DRIVER protocol version is ', DRV_latest_protocol_version
00144          call psmile_abort
00145 
00146       ENDIF
00147 !
00148 ! 1.2.2. Number of applications and components is distributed to all
00149 !        processes. The data is sent by the root of the coupler processes.
00150 !       ibuf (4) = Total number of rank sets for the different components
00151       il_dim_buf = 3
00152       ALLOCATE(ila_buf(il_dim_buf), stat=id_err)
00153       IF (id_err > 0) THEN
00154           ierrp (1) = id_err
00155           ierrp (2) = il_dim_buf
00156           id_err = PRISM_Error_Alloc
00157 
00158           call psmile_error_common ( id_err, 'ila_buf', &
00159              ierrp, 2, __FILE__, __LINE__ )
00160           RETURN
00161       ENDIF
00162 
00163       ila_buf (1) = ig_nb_appl
00164       ila_buf (2) = ig_nb_tot_comps
00165 
00166       IF ( ig_nb_appl .eq. 0 ) THEN
00167           ila_buf (3) = 1 ! Indicating stand alone
00168       ELSE
00169           ila_buf (3) = 0 ! Indicating coupler mode
00170       ENDIF
00171       ila_buf (3) = 0
00172 
00173       CALL MPI_Bcast( ila_buf, il_dim_buf, MPI_Integer, &
00174          PRISMdrv_root, comm_drv_global, id_err )
00175 
00176       IF ( id_err /= MPI_SUCCESS ) THEN
00177           ierrp (1) = id_err
00178           id_err = PRISM_Error_MPI
00179 
00180       call psmile_error_common ( id_err, 'MPI_Bcast', &
00181           ierrp, 1, __FILE__, __LINE__ )
00182           RETURN
00183       ENDIF
00184 
00185       ig_nb_appl      = ila_buf (1)
00186       ig_nb_tot_comps = ila_buf (2)
00187 
00188       DEALLOCATE(ila_buf, stat=id_err)
00189       IF (id_err > 0) THEN
00190           ierrp (1) = id_err
00191           ierrp (2) = il_dim_buf
00192           id_err = PRISM_Error_Alloc
00193 
00194           call psmile_error_common ( id_err, 'ila_buf', &
00195              ierrp, 2, __FILE__, __LINE__ )
00196           RETURN
00197       ENDIF
00198 
00199 ! 1.2.3. Number of processes per application is distributed to all process
00200       CALL MPI_Bcast(iga_appli_nb_pes(0), ig_nb_appl+1, MPI_Integer, &
00201          PRISMdrv_root, comm_drv_global, id_err )
00202 
00203       IF ( id_err /= MPI_SUCCESS ) THEN
00204           ierrp (1) = id_err
00205           id_err = PRISM_Error_MPI
00206 
00207           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00208              __FILE__, __LINE__ )
00209           RETURN
00210       ENDIF
00211 
00212 ! 1.2.5. Broadcast names of applications
00213       CALL MPI_Bcast(cga_appli_name(0), (ig_nb_appl+1)*max_name, &
00214          MPI_Character, PRISMdrv_root, comm_drv_global, id_err )
00215 
00216       IF ( id_err /= MPI_SUCCESS ) THEN
00217           ierrp (1) = id_err
00218           id_err = PRISM_Error_MPI
00219 
00220           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00221              __FILE__, __LINE__ )
00222           RETURN
00223       ENDIF
00224 
00225 ! 1.2.6. Broadcast names of components
00226       CALL MPI_Bcast(cga_appli_compname(1), (ig_nb_tot_comps)*max_name, &
00227          MPI_Character, PRISMdrv_root, comm_drv_global, id_err )
00228 
00229       IF ( id_err /= MPI_SUCCESS ) THEN
00230           ierrp (1) = id_err
00231           id_err = PRISM_Error_MPI
00232 
00233           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00234              __FILE__, __LINE__ )
00235           RETURN
00236       ENDIF
00237 
00238 ! 1.2.7. Broadcast the number of components of all applications
00239       CALL MPI_Bcast( iga_appli_nb_comps(1), ig_nb_appl, &
00240          MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00241 
00242       if ( id_err /= MPI_SUCCESS ) then
00243           ierrp (1) = id_err
00244           id_err = PRISM_Error_MPI
00245           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00246              __FILE__, __LINE__ )
00247           return
00248       endif
00249 
00250 ! 1.2.9. Broadcast the rank sets for all the components
00251       CALL MPI_Bcast( iga_appli_compnbranksets(1), ig_nb_tot_comps, &
00252          MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00253 
00254       if ( id_err /= MPI_SUCCESS ) then
00255           ierrp (1) = id_err
00256           id_err = PRISM_Error_MPI
00257           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00258              __FILE__, __LINE__ )
00259           return
00260       endif
00261 
00262       CALL MPI_Bcast( iga_appli_compranks, ig_nbtot_ranksets*3, &
00263          MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00264 
00265       if ( id_err /= MPI_SUCCESS ) then
00266           ierrp (1) = id_err
00267           id_err = PRISM_Error_MPI
00268           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00269              __FILE__, __LINE__ )
00270           return
00271       endif
00272 
00273 ! 1.2.10. Broadcast redirect stdout info for all applications
00274       CALL MPI_Bcast( iga_appli_redirect(1), ig_nb_appl, &
00275          MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00276 
00277       if ( id_err /= MPI_SUCCESS ) then
00278           ierrp (1) = id_err
00279           id_err = PRISM_Error_MPI
00280           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00281              __FILE__, __LINE__ )
00282           return
00283       endif
00284 
00285 ! 1.3. Define the local communicators
00286 
00287       call prismdrv_def_mpi_comm(id_err)
00288 
00289 ! 1.4  Determine the application rank (has already been defined in prismdrv_init, but there is was the global rank)
00290 
00291       call MPI_COMM_RANK ( comm_drv_local, Appl%rank, id_err )
00292 
00293       if ( id_err /= MPI_SUCCESS ) THEN
00294           ierrp (1) = id_err
00295           call psmile_error_common ( PRISM_Error_MPI, 'MPI_Comm_rank', &
00296              ierrp, 1, __FILE__, __LINE__ )
00297           return
00298       endif
00299 
00300 #ifdef VERBOSE
00301       PRINT *, '| | End MPI1 implementation'
00302       call psmile_flushstd
00303 #endif
00304 !
00305 ! 2. Process management if MPI2 and spawn
00306 !
00307 
00308   ELSE IF (ig_MPI .eq. DRV_MPI2) THEN
00309 
00310 #ifdef VERBOSE
00311       PRINT *, '| | MPI2 implementation'
00312       call psmile_flushstd
00313 #endif
00314 ! 2.1. If MPI2, Duplicate MPI_COMM_WORLD to get comm_drv
00315 
00316       CALL MPI_Comm_dup (MPI_COMM_WORLD, comm_drv_local, id_err)
00317 
00318       IF ( id_err /= MPI_SUCCESS ) THEN
00319           ierrp (1) = id_err
00320           id_err = PRISM_Error_MPI
00321 
00322           call psmile_error_common ( id_err, 'MPI_Comm_dup', &
00323              ierrp, 1, __FILE__, __LINE__ )
00324           RETURN
00325       ENDIF
00326 
00327       CALL MPI_Comm_dup (MPI_COMM_WORLD, comm_drv_global, id_err)
00328 
00329       IF ( id_err /= MPI_SUCCESS ) THEN
00330           ierrp (1) = id_err
00331           id_err = PRISM_Error_MPI
00332 
00333           call psmile_error_common ( id_err, 'MPI_Comm_dup', &
00334              ierrp, 1, __FILE__, __LINE__ )
00335           RETURN
00336       ENDIF
00337 
00338 ! 2.2. Spawn applications on hosts with prismdrv_spawn_child
00339 
00340 ! 2.2.0 Set the part of the sent buffer that won't change
00341 
00342       il_dim_buf = 4
00343       ALLOCATE(ila_buf(il_dim_buf), stat=id_err)
00344       IF (id_err > 0) THEN
00345           ierrp (1) = id_err
00346           ierrp (2) = il_dim_buf
00347           id_err = PRISM_Error_Alloc
00348 
00349           call psmile_error_common ( id_err, 'ila_buf', &
00350              ierrp, 2, __FILE__, __LINE__ )
00351           RETURN
00352       ENDIF
00353 
00354       ila_buf(1) = DRV_latest_protocol_version
00355       ila_buf(2) = ig_nb_appl
00356       ila_buf(4) = ig_nb_tot_comps
00357 
00358       n_host = 1 ! pointer to the position of the current application
00359       n_args = 1 ! pointer to the position of the current application
00360 
00361       DO ib = 1, ig_nb_appl
00362 
00363 ! 2.2.1. Spawn application ib on iga_nb_hosts_appl(ib) hosts
00364 
00365         IF ( Appl%rank == PRISM_Root ) THEN
00366            PRINT *, '| | | MPI2 Spawning processes:  '
00367            PRINT *, '| | | MPI2 Spawning exe_name    ', trim(cga_appli_exe_name(ib))
00368            PRINT *, '| | | MPI2 Spawning appli_args  ', trim(cga_appli_args(n_args))
00369            PRINT *, '| | | MPI2 Spawning nb_args     ', iga_appli_nb_args(ib)
00370            PRINT *, '| | | MPI2 Spawning nb_hosts    ', iga_appli_nb_hosts(ib)
00371            DO ib_bis = n_host,n_host+iga_appli_nb_hosts(ib)-1
00372                PRINT *, '| | | MPI2 Spawning nb_pes      ', iga_appli_hostnbprocs(ib_bis)
00373                PRINT *, '| | | MPI2 Spawning on hostname ', trim(cga_appli_hostname(ib_bis))
00374            ENDDO
00375         ENDIF
00376 
00377         call prismdrv_spawn_child (cga_appli_exe_name(ib),       &
00378            cga_appli_args(n_args), iga_appli_nb_args(ib), ib,  &
00379            iga_appli_nb_hosts(ib), cga_appli_hostname(n_host), &
00380            iga_appli_hostnbprocs(n_host), comm_drv_global,     &
00381            il_inter, id_err)
00382 
00383         n_host = n_host + iga_appli_nb_hosts(ib)
00384         n_args = n_args + iga_appli_nb_args(ib)
00385 
00386 ! 2.2.2. Exchange protocol version with psmile lib
00387 !          The protocol version is sent by the root process of the appl.
00388 
00389         IF ( Appl%rank == PRISM_Root ) THEN
00390            CALL MPI_Recv (il_protocol_version, 1, MPI_Integer, &
00391                 PRISM_root, PSMILe_Init_tag, il_inter, &
00392                 il_status, id_err)
00393 
00394            IF ( id_err /= MPI_SUCCESS ) THEN
00395               ierrp (1) = id_err
00396               ierrp (2) = PRISM_root
00397               ierrp (3) = PSMILe_Init_tag
00398 
00399               id_err = PRISM_Error_Recv
00400 
00401               call psmile_error_common ( id_err, 'MPI_Recv', &
00402                    ierrp, 3, __FILE__, __LINE__ )
00403               RETURN
00404            ENDIF
00405 
00406 ! 2.2.3. Send initial data to root of spawned processes
00407 !
00408 !     ibuf (1) = Protocol version of the coupler
00409 !     ibuf (2) = Number of application
00410 !     ibuf (3) = Sequence number of current application
00411 !     ibuf (4) = Total number of rank sets for the different components
00412 
00413            ila_buf(3) = ib
00414 
00415            CALL MPI_Send(ila_buf, il_dim_buf, MPI_Integer, &
00416                 PRISM_root, PSMILe_Init_tag, il_inter, &
00417                 id_err)
00418 
00419            IF ( id_err /= MPI_SUCCESS ) THEN
00420               ierrp (1) = id_err
00421               ierrp (2) = PRISM_root
00422               ierrp (3) = PSMILe_Init_tag
00423               id_err = PRISM_Error_Send
00424 
00425               call psmile_error_common ( PRISM_Error_Send, 'MPI_Send', &
00426                    ierrp, 3, __FILE__, __LINE__ )
00427               RETURN
00428            ENDIF
00429         ENDIF
00430 
00431       DEALLOCATE(ila_buf, stat=id_err)
00432       IF (id_err > 0) THEN
00433           ierrp (1) = id_err
00434           ierrp (2) = il_dim_buf
00435           id_err = PRISM_Error_Alloc
00436 
00437           call psmile_error_common ( id_err, 'ila_buf', &
00438              ierrp, 2, __FILE__, __LINE__ )
00439           RETURN
00440       ENDIF
00441 
00442 ! 2.2.4. Merge the communicators to get comm_drv_global
00443 
00444         !flag is set to false => driver gets the lower ranks => PRISM_root == PRISMdrv_root == 0
00445         ll_flag = .false.
00446 
00447         CALL MPI_Intercomm_merge (il_inter, ll_flag, comm_drv_global, &
00448            id_err)
00449 
00450         IF ( id_err /= 0 ) THEN
00451             ierrp (1) = id_err
00452             id_err = PRISM_Error_MPI
00453 
00454             call psmile_error_common ( id_err, 'MPI_Intercomm_merge', &
00455                ierrp, 1, __FILE__, __LINE__ )
00456             RETURN
00457         ENDIF
00458 
00459 ! 2.2.4bis. The resulting communicator is the global communicator
00460 
00461         CALL MPI_Comm_rank ( comm_drv_global, global_rank, id_err )
00462 
00463         IF ( id_err /= MPI_SUCCESS ) THEN
00464             ierrp (1) = id_err
00465             id_err = PRISM_Error_MPI
00466 
00467             call psmile_error_common ( id_err, 'MPI_Comm_rank', &
00468                ierrp, 1, __FILE__, __LINE__ )
00469             RETURN
00470         ENDIF
00471 
00472 ! 2.2.5. Free the communicators
00473 
00474         IF (ib /= 1) THEN
00475 
00476             CALL MPI_Comm_free (il_inter, id_err)
00477 
00478             IF ( id_err /= 0 ) THEN
00479                 ierrp (1) = id_err
00480                 id_err = PRISM_Error_MPI
00481 
00482                 call psmile_error_common ( id_err, 'MPI_Comm_free', &
00483                    ierrp, 1, __FILE__, __LINE__ )
00484                 RETURN
00485             ENDIF
00486 
00487         ELSE
00488 
00489             comm_coupling (ib) = comm_drv_global
00490 
00491         ENDIF
00492 
00493       END DO
00494 
00495 ! 2.4. Duplicate the global communicator to Get the transformer comm
00496 
00497       CALL MPI_Comm_dup (comm_drv_global, comm_drv_trans, id_err)
00498 
00499       IF ( id_err /= MPI_SUCCESS ) THEN
00500           ierrp (1) = id_err
00501           id_err = PRISM_Error_MPI
00502 
00503           call psmile_error_common ( id_err, 'MPI_Comm_dup', &
00504              ierrp, 1, __FILE__, __LINE__ )
00505           RETURN
00506       ENDIF
00507 
00508 
00509 ! 2.5. Broadcast the protocol version
00510 
00511       CALL MPI_Bcast ( il_protocol_version, 1, MPI_Integer, &
00512          PRISMdrv_root, comm_drv_global, id_err )
00513 
00514       IF ( id_err /= MPI_SUCCESS ) THEN
00515           ierrp (1) = id_err
00516           id_err = PRISM_Error_MPI
00517           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00518              __FILE__, __LINE__ )
00519           RETURN
00520       ENDIF
00521 
00522 
00523 ! 2.5. Broadcast the number of pes per application
00524 
00525       call MPI_Bcast( iga_appli_nb_pes(0), ig_nb_appl+1, MPI_Integer, &
00526          PRISMdrv_root, comm_drv_global, id_err )
00527 
00528       IF ( id_err /= MPI_SUCCESS ) THEN
00529           ierrp (1) = id_err
00530           id_err = PRISM_Error_MPI
00531           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00532              __FILE__, __LINE__ )
00533           RETURN
00534       ENDIF
00535 
00536 
00537 ! 2.9. Broadcast names of all applications and components
00538 !
00539 ! 2.9.1 Broadcast names of all applications
00540       CALL MPI_Bcast( cga_appli_name(0), (ig_nb_appl+1)*max_name, &
00541          MPI_Character, PRISMdrv_root, comm_drv_global, id_err )
00542 
00543       if ( id_err /= MPI_SUCCESS ) then
00544           ierrp (1) = id_err
00545           id_err = PRISM_Error_MPI
00546           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00547              __FILE__, __LINE__ )
00548           return
00549       endif
00550 
00551 ! 2.9.2. Broadcast names of components
00552       CALL MPI_Bcast(cga_appli_compname(1), (ig_nb_tot_comps)*max_name, &
00553          MPI_Character, PRISMdrv_root, comm_drv_global, id_err )
00554 
00555       IF ( id_err /= MPI_SUCCESS ) THEN
00556           ierrp (1) = id_err
00557           id_err = PRISM_Error_MPI
00558 
00559           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00560              __FILE__, __LINE__ )
00561           RETURN
00562       ENDIF
00563 
00564 ! 2.9.4. Broadcast the number of components per application
00565 
00566       call MPI_Bcast( iga_appli_nb_comps(1), ig_nb_appl, &
00567          MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00568 
00569       if ( id_err /= MPI_SUCCESS ) then
00570           ierrp (1) = id_err
00571           id_err = PRISM_Error_MPI
00572           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00573              __FILE__, __LINE__ )
00574           return
00575       endif
00576 
00577 ! 2.9.5. Broadcast the rank sets for all the components
00578       CALL MPI_Bcast( iga_appli_compnbranksets(1), ig_nb_tot_comps, &
00579          MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00580 
00581       if ( id_err /= MPI_SUCCESS ) then
00582           ierrp (1) = id_err
00583           id_err = PRISM_Error_MPI
00584           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00585              __FILE__, __LINE__ )
00586           return
00587       endif
00588 
00589       CALL MPI_Bcast( iga_appli_compranks, ig_nbtot_ranksets*3, &
00590          MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00591 
00592       if ( id_err /= MPI_SUCCESS ) then
00593           ierrp (1) = id_err
00594           id_err = PRISM_Error_MPI
00595           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00596              __FILE__, __LINE__ )
00597           return
00598       endif
00599 
00600 ! 2.9.6. Broadcast redirect stdout info for all applications
00601       CALL MPI_Bcast( iga_appli_redirect(1), ig_nb_appl, &
00602          MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00603 
00604       if ( id_err /= MPI_SUCCESS ) then
00605           ierrp (1) = id_err
00606           id_err = PRISM_Error_MPI
00607           call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00608              __FILE__, __LINE__ )
00609           return
00610       endif
00611 
00612 ! 2.10. Split global communicator in order to get a communicator
00613 !       between the driver and the application
00614 
00615       do ib = 2, ig_nb_appl
00616 
00617         call MPI_Comm_split (comm_drv_global, ib, PRISM_Root, &
00618            comm_coupling(ib), id_err)
00619 
00620         if ( id_err /= MPI_SUCCESS ) then
00621             ierrp (1) = id_err
00622             id_err = PRISM_Error_MPI
00623 
00624             call psmile_error_common ( id_err, 'MPI_Comm_split', &
00625                ierrp, 1, __FILE__, __LINE__ )
00626             return
00627         endif
00628 
00629       enddo
00630 
00631 ! 2.11. Construct a communicator comm_psmile containing all MPI processes
00632 !       which are connected to the PSMILe library
00633 
00634       call MPI_Comm_Split ( comm_drv_global, MPI_UNDEFINED, 0,  &
00635          comm_drv_psmile, id_err )
00636 
00637       if ( id_err /= MPI_SUCCESS ) then
00638           ierrp (1) = id_err
00639           id_err = PRISM_Error_MPI
00640 
00641           call psmile_error_common ( id_err, 'MPI_Comm_Split', &
00642              ierrp, 1, __FILE__, __LINE__ )
00643           return
00644       endif
00645 
00646 #ifdef VERBOSE
00647       PRINT *, '| | End MPI2 implementation'
00648       call psmile_flushstd
00649 #endif
00650   END IF
00651 !
00652 ! 2.12  Initialize driver's internal timers
00653 !
00654 #ifdef PROFILE
00655   timer_label = 'main'
00656   call psmile_timer_init (1, timer_label, 'Driver', 'driver_timer_stats', comm_drv_local)
00657   call psmile_timer_start(1)
00658 #endif
00659 !
00660 
00661 ! 3. Broadcast sga_run_start_date and sga_experiment_start_date
00662 !    2 vectors of integers and doubles are set with the date
00663 !    and then broadcasted.
00664 !    set the vectors for ig_run_start_date
00665 
00666   ila_date(1)  = sga_run_start_date%year
00667   ila_date(2)  = sga_run_start_date%month
00668   ila_date(3)  = sga_run_start_date%day
00669   ila_date(4)  = sga_run_start_date%hour
00670   ila_date(5)  = sga_run_start_date%minute
00671   dla_date(1)  = sga_run_start_date%second
00672 
00673 !    set the vectors for ig_run_end_date
00674 
00675   ila_date(6)  = sga_run_end_date%year
00676   ila_date(7)  = sga_run_end_date%month
00677   ila_date(8)  = sga_run_end_date%day
00678   ila_date(9)  = sga_run_end_date%hour
00679   ila_date(10) = sga_run_end_date%minute
00680   dla_date(2)  = sga_run_end_date%second
00681 
00682 !    set the vectors for ig_experiment_start_date
00683 
00684   ila_date(11) = sga_experiment_start_date%year
00685   ila_date(12) = sga_experiment_start_date%month
00686   ila_date(13) = sga_experiment_start_date%day
00687   ila_date(14) = sga_experiment_start_date%hour
00688   ila_date(15) = sga_experiment_start_date%minute
00689   dla_date(3)  = sga_experiment_start_date%second
00690 
00691 !    broacast the two vectors
00692 
00693   CALL MPI_Bcast( ila_date(1), 15, &
00694        MPI_Integer, PRISMdrv_root, comm_drv_global, id_err )
00695 
00696   if ( id_err /= MPI_SUCCESS ) then
00697      ierrp (1) = id_err
00698      id_err = PRISM_Error_MPI
00699      call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00700           __FILE__, __LINE__ )
00701      return
00702   endif
00703 
00704   CALL MPI_Bcast( dla_date(1), 3, &
00705        MPI_Double_Precision, PRISMdrv_root, comm_drv_global, id_err )
00706 
00707   if ( id_err /= MPI_SUCCESS ) then
00708      ierrp (1) = id_err
00709      id_err = PRISM_Error_MPI
00710      call psmile_error_common ( id_err, 'MPI_Bcast', ierrp, 1, &
00711           __FILE__, __LINE__ )
00712      return
00713   endif
00714 
00715 !
00716 ! 4. Give the comp_id to all the components processes
00717 !
00718 ! 4.1. Get the global size and thus the dimensioning number of the process
00719 !      management stucture
00720 !
00721   CALL MPI_Comm_size (comm_drv_global, il_size, id_err)
00722 
00723   IF ( id_err /= MPI_SUCCESS ) THEN
00724       ierrp (1) = id_err
00725       id_err = PRISM_Error_MPI
00726       call psmile_error_common ( id_err, 'MPI_Comm_size', ierrp, 1, &
00727          __FILE__, __LINE__ )
00728       RETURN
00729   ENDIF
00730 
00731   IF ( il_size <= ig_driver_nb_pes ) THEN
00732      PRINT *, '| | Number of driver processes started was      ', ig_driver_nb_pes
00733      PRINT *, '| | Number of application processes started was ', ig_driver_nb_pes-il_size
00734      PRINT *, '| | Number of total processes started was       ', il_size
00735      ierrp (1) = ig_driver_nb_pes-il_size
00736      ierrp (2) = PRISM_UNDEFINED
00737      call psmile_error_common ( PRISM_Error_InitApp, 'Inconsistent mpirun command and scc.xml', &
00738           ierrp, 2, __FILE__, __LINE__ )
00739   ENDIF
00740 
00741 ! 4.2. Allocate the Drv_Proc_manage structure
00742   ALLOCATE(Drv_Procs(il_size), stat = id_err)
00743 
00744   IF ( id_err > 0 ) THEN
00745       ierrp (1) = id_err
00746       ierrp (2) = il_size
00747       call psmile_error_common ( PRISM_Error_Alloc, 'PRISM_comm_global_size', &
00748          ierrp, 2, __FILE__, __LINE__ )
00749   ENDIF
00750 
00751   IF (Appl%rank == PRISM_root ) THEN
00752 ! 4.3. Receive the application name from each application process
00753 
00754 !     for all processes in comm_drv_global
00755       DO ib = 0, il_size - 1
00756 !       if rank does not belong to a driver process
00757         IF ((ib < PRISMdrv_root) .OR. ((PRISMdrv_root + ig_driver_nb_pes) <= ib)) THEN
00758 ! dd 25/02/04 this is a workaround patch. On the sun the exchanges of names
00759 !             give wrong values to the driver
00760           CALL MPI_Recv (Drv_Procs(ib+1)%appli_name, max_name, MPI_Character, &
00761              ib, 1, comm_drv_global, il_status, id_err)
00762           CALL MPI_Recv (Drv_Procs(ib+1)%comps_per_rank, 1, MPI_Integer, &
00763              ib, 1, comm_drv_global, il_status, id_err)
00764           IF ( Drv_Procs(ib+1)%comps_per_rank > 0 ) THEN
00765              ALLOCATE(Drv_Procs(ib+1)%comp_name(Drv_Procs(ib+1)%comps_per_rank))
00766              ALLOCATE(Drv_Procs(ib+1)%global_rank(Drv_Procs(ib+1)%comps_per_rank))
00767              ALLOCATE(Drv_Procs(ib+1)%global_comp_id(Drv_Procs(ib+1)%comps_per_rank))
00768           ENDIF
00769 #ifdef DEBUG
00770           PRINT *, '| | application name ', trim(Drv_Procs(ib+1)%appli_name)
00771           PRINT *, '| | with             ', Drv_Procs(ib+1)%comps_per_rank, 'comps on rank ', ib
00772           CALL psmile_flushstd
00773 #endif
00774         ENDIF
00775       ENDDO
00776 ! 4.4. Receive the component names from each application process and send
00777 !         back global component Id
00778 
00779 !     for all processes in comm_drv_global
00780       DO ib = 0, il_size - 1
00781 !       if rank does not belong to a driver process
00782         IF ((ib < PRISMdrv_root) .OR. ((PRISMdrv_root + ig_driver_nb_pes) <= ib)) THEN
00783           DO ib_bis = 1, Drv_Procs(ib+1)%comps_per_rank
00784 #ifdef DEBUG
00785             PRINT *, '| | receive a component name from ', ib
00786             CALL psmile_flushstd
00787 #endif
00788             CALL MPI_Recv (Drv_Procs(ib+1)%comp_name(ib_bis), max_name, MPI_Character, &
00789                  ib, 1, comm_drv_global, il_status, id_err)
00790 #ifdef DEBUG
00791             PRINT *, '| | received component name ', trim(Drv_Procs(ib+1)%comp_name(ib_bis)), ' from ', ib
00792             CALL psmile_flushstd
00793 #endif
00794 
00795             IF ( id_err /= MPI_SUCCESS ) THEN
00796                ierrp (1) = id_err
00797                id_err = PRISM_Error_MPI
00798                call psmile_error_common ( id_err, 'MPI_Recv', ierrp, 1, &
00799                     __FILE__, __LINE__ )
00800                RETURN
00801             ENDIF
00802 
00803             Drv_Procs(ib+1)%global_rank(ib_bis) = ib
00804             Drv_Procs(ib+1)%global_comp_id(ib_bis) = huge(il_comp_index)
00805 
00806             il_comp_index = 0
00807             OUTER: DO ib_ter = 1, ig_nb_appl
00808 
00809              DO ib_quad = 1, iga_appli_nb_comps(ib_ter)
00810 
00811                 il_comp_index = il_comp_index + 1
00812 
00813 #ifdef DEBUG
00814             PRINT *, '| | testing application name "', &
00815                TRIM(cga_appli_name(ib_ter)), '" == "', TRIM(Drv_Procs(ib+1)%appli_name), '" = ', &
00816                (TRIM(cga_appli_name(ib_ter)) .eq. TRIM(Drv_Procs(ib+1)%appli_name))
00817             CALL psmile_flushstd
00818 #endif
00819 
00820                 IF (TRIM(cga_appli_name(ib_ter)) .eq. &
00821                      TRIM(Drv_Procs(ib+1)%appli_name)) THEN
00822 #ifdef DEBUG
00823                   PRINT *, '| | testing component name "', &
00824                      TRIM(cga_appli_compname(il_comp_index)), '" == "', &
00825                      TRIM(Drv_Procs(ib+1)%comp_name(ib_bis)), '" = ', &
00826                      (TRIM(cga_appli_compname(il_comp_index)) .eq. TRIM(Drv_Procs(ib+1)%comp_name(ib_bis)))
00827                   CALL psmile_flushstd
00828 #endif
00829                    IF (TRIM(cga_appli_compname(il_comp_index)) .eq. &
00830                         TRIM(Drv_Procs(ib+1)%comp_name(ib_bis))) THEN
00831                       Drv_Procs(ib+1)%global_comp_id(ib_bis) = il_comp_index
00832                       EXIT OUTER
00833                    END IF
00834                 END IF
00835                END DO !ib_quad
00836             END DO OUTER ! ib_ter
00837 
00838             IF (Drv_Procs(ib+1)%global_comp_id(ib_bis) == huge(il_comp_index)) then
00839                ierrp (1) = Drv_Procs(ib+1)%global_comp_id(ib_bis)
00840                id_err = PRISM_Error_Comp_name
00841 
00842                call psmile_error_common ( id_err, 'could not find matching component', &
00843                                           ierrp, 1, __FILE__, __LINE__ )
00844                RETURN
00845             ENDIF
00846 
00847             CALL MPI_Send (Drv_Procs(ib+1)%global_comp_id(ib_bis), 1, &
00848                 MPI_INTEGER, ib, 2, comm_drv_global, id_err)
00849 #ifdef DEBUG
00850             PRINT *, '| | send global comp ID ', Drv_Procs(ib+1)%global_comp_id(ib_bis), ' to ', ib
00851             CALL psmile_flushstd
00852 #endif
00853              IF ( id_err /= MPI_SUCCESS ) THEN
00854                 ierrp (1) = id_err
00855                 id_err = PRISM_Error_MPI
00856                 call psmile_error_common ( id_err, 'MPI_Send', ierrp, 1, &
00857                      __FILE__, __LINE__ )
00858                 RETURN
00859              ENDIF
00860 
00861           END DO ! ib_bis
00862         END IF
00863 
00864       END DO ! ib
00865 
00866   ENDIF
00867 !
00868 #ifdef VERBOSE
00869   PRINT *, '| Quit PRISMDrv_Init_appl'
00870   PRINT *, '|'
00871   call psmile_flushstd
00872 #endif
00873 END SUBROUTINE PRISMDrv_Init_appl

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1