source: palm/trunk/SOURCE/pmc_child_mod.f90 @ 3241

Last change on this file since 3241 was 3241, checked in by raasch, 6 years ago

various changes to avoid compiler warnings (mainly removal of unused variables)

  • Property svn:keywords set to Id
File size: 28.9 KB
RevLine 
[1933]1MODULE pmc_child
[1762]2
[2000]3!------------------------------------------------------------------------------!
[2696]4! This file is part of the PALM model system.
[1762]5!
[2000]6! PALM is free software: you can redistribute it and/or modify it under the
7! terms of the GNU General Public License as published by the Free Software
8! Foundation, either version 3 of the License, or (at your option) any later
9! version.
[1762]10!
11! PALM is distributed in the hope that it will be useful, but WITHOUT ANY
12! WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13! A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
14!
15! You should have received a copy of the GNU General Public License along with
16! PALM. If not, see <http://www.gnu.org/licenses/>.
17!
[2718]18! Copyright 1997-2018 Leibniz Universitaet Hannover
[2000]19!------------------------------------------------------------------------------!
[1762]20!
21! Current revisions:
22! ------------------
[1834]23!
[2001]24!
[1762]25! Former revisions:
26! -----------------
27! $Id: pmc_child_mod.f90 3241 2018-09-12 15:02:00Z raasch $
[3241]28! unused variables removed
29!
30! 2841 2018-02-27 15:02:57Z knoop
[2841]31! Bugfix: wrong placement of include 'mpif.h' corrected
32!
33! 2809 2018-02-15 09:55:58Z schwenkel
[2809]34! Bugfix for gfortran: Replace the function C_SIZEOF with STORAGE_SIZE
35!
36! 2801 2018-02-14 16:01:55Z thiele
[2801]37! Introduce particle transfer in nested models.
38!
39! 2718 2018-01-02 08:49:38Z maronga
[2716]40! Corrected "Former revisions" section
41!
42! 2696 2017-12-14 17:12:51Z kanani
43! Change in file header (GPL part)
44!
45! 2599 2017-11-01 13:18:45Z hellstea
[2599]46! Some cleanup and commenting improvements only.
47!
48! 2101 2017-01-05 16:42:31Z suehring
[1762]49!
[2001]50! 2000 2016-08-20 18:09:15Z knoop
51! Forced header and separation lines into 80 columns
52!
[1933]53! 1897 2016-05-03 08:10:23Z raasch
54! Module renamed. Code clean up. The words server/client changed to parent/child.
55!
[1897]56! 1896 2016-05-03 08:06:41Z raasch
57! re-formatted to match PALM style
58!
[1851]59! 1850 2016-04-08 13:29:27Z maronga
60! Module renamed
61!
62!
[1834]63! 1833 2016-04-07 14:23:03Z raasch
64! gfortran requires pointer attributes for some array declarations,
65! long line wrapped
66!
[1809]67! 1808 2016-04-05 19:44:00Z raasch
68! MPI module used by default on all machines
69!
[1798]70! 1797 2016-03-21 16:50:28Z raasch
71! introduction of different datatransfer modes
72!
[1792]73! 1791 2016-03-11 10:41:25Z raasch
74! Debug write-statement commented out
75!
[1787]76! 1786 2016-03-08 05:49:27Z raasch
[1933]77! change in child-parent data transfer: parent now gets data from child
78! instead of that child puts it to the parent
[1787]79!
[1784]80! 1783 2016-03-06 18:36:17Z raasch
81! Bugfix: wrong data-type in MPI_WIN_CREATE replaced
82!
[1780]83! 1779 2016-03-03 08:01:28Z raasch
84! kind=dp replaced by wp, dim_order removed
85! array management changed from linked list to sequential loop
86!
[1765]87! 1764 2016-02-28 12:45:19Z raasch
88! cpp-statement added (nesting can only be used in parallel mode),
89! all kinds given in PALM style
90!
[1763]91! 1762 2016-02-25 12:31:13Z hellstea
92! Initial revision by K. Ketelsen
[1762]93!
94! Description:
95! ------------
96!
[1933]97! Child part of Palm Model Coupler
[2801]98!------------------------------------------------------------------------------!
[1762]99
[1764]100#if defined( __parallel )
[1762]101
[1896]102    USE, INTRINSIC ::  iso_c_binding
[1762]103
[2841]104#if !defined( __mpifh )
[1764]105    USE MPI
106#endif
[1896]107
108    USE kinds
[2841]109
[2801]110    USE pmc_general,                                                           &
111        ONLY:  arraydef, childdef, da_desclen, da_namedef, da_namelen, pedef,  &
[1896]112               pmc_da_name_err,  pmc_g_setname, pmc_max_array, pmc_status_ok
113
[2801]114    USE pmc_handle_communicator,                                               &
[1933]115        ONLY:  m_model_comm, m_model_npes, m_model_rank, m_to_parent_comm
[1896]116
[2801]117    USE pmc_mpi_wrapper,                                                       &
[1933]118        ONLY:  pmc_alloc_mem, pmc_bcast, pmc_inter_bcast, pmc_time
[1896]119
120    IMPLICIT NONE
121
[2841]122#if defined( __mpifh )
123    INCLUDE "mpif.h"
124#endif
125
[1762]126    PRIVATE
127    SAVE
128
[2801]129    TYPE(childdef), PUBLIC ::  me   !<
[1762]130
[2801]131    INTEGER(iwp) ::  myindex = 0         !< counter and unique number for data arrays
132    INTEGER(iwp) ::  next_array_in_list = 0   !<
[1762]133
134
[1933]135    INTERFACE pmc_childinit
136        MODULE PROCEDURE pmc_childinit
137    END INTERFACE pmc_childinit
[1762]138
[1896]139    INTERFACE pmc_c_clear_next_array_list
140        MODULE PROCEDURE pmc_c_clear_next_array_list
141    END INTERFACE pmc_c_clear_next_array_list
[1762]142
[1896]143    INTERFACE pmc_c_getbuffer
144        MODULE PROCEDURE pmc_c_getbuffer
145    END INTERFACE pmc_c_getbuffer
[1762]146
[1896]147    INTERFACE pmc_c_getnextarray
148        MODULE PROCEDURE pmc_c_getnextarray
149    END INTERFACE pmc_c_getnextarray
[1779]150
[1896]151    INTERFACE pmc_c_get_2d_index_list
152        MODULE PROCEDURE pmc_c_get_2d_index_list
153    END INTERFACE pmc_c_get_2d_index_list
[1762]154
[1896]155    INTERFACE pmc_c_putbuffer
156        MODULE PROCEDURE pmc_c_putbuffer
157    END INTERFACE pmc_c_putbuffer
[1762]158
[1896]159    INTERFACE pmc_c_setind_and_allocmem
160        MODULE PROCEDURE pmc_c_setind_and_allocmem
161    END INTERFACE pmc_c_setind_and_allocmem
[1762]162
[1896]163    INTERFACE pmc_c_set_dataarray
164        MODULE PROCEDURE pmc_c_set_dataarray_2d
165        MODULE PROCEDURE pmc_c_set_dataarray_3d
[2801]166        MODULE PROCEDURE pmc_c_set_dataarray_ip2d
[1896]167    END INTERFACE pmc_c_set_dataarray
[1762]168
[1896]169    INTERFACE pmc_set_dataarray_name
170        MODULE PROCEDURE pmc_set_dataarray_name
171        MODULE PROCEDURE pmc_set_dataarray_name_lastentry
172    END INTERFACE pmc_set_dataarray_name
[1762]173
174
[2801]175    PUBLIC pmc_childinit, pmc_c_clear_next_array_list, pmc_c_getbuffer,        &
176           pmc_c_getnextarray, pmc_c_putbuffer, pmc_c_setind_and_allocmem,     &
[1896]177           pmc_c_set_dataarray, pmc_set_dataarray_name, pmc_c_get_2d_index_list
[1762]178
[1896]179 CONTAINS
[1762]180
181
182
[1933]183 SUBROUTINE pmc_childinit
[1762]184
[1896]185     IMPLICIT NONE
[1762]186
[2801]187     INTEGER(iwp) ::  i        !<
188     INTEGER(iwp) ::  istat    !<
[1762]189
[1896]190!
191!--  Get / define the MPI environment
192     me%model_comm = m_model_comm
[1933]193     me%inter_comm = m_to_parent_comm
[1762]194
[1896]195     CALL MPI_COMM_RANK( me%model_comm, me%model_rank, istat )
196     CALL MPI_COMM_SIZE( me%model_comm, me%model_npes, istat )
197     CALL MPI_COMM_REMOTE_SIZE( me%inter_comm, me%inter_npes, istat )
198!
[2599]199!--  Intra-communicator is used for MPI_GET
[1896]200     CALL MPI_INTERCOMM_MERGE( me%inter_comm, .TRUE., me%intra_comm, istat )
201     CALL MPI_COMM_RANK( me%intra_comm, me%intra_rank, istat )
[1762]202
[1896]203     ALLOCATE( me%pes(me%inter_npes) )
[1779]204!
[2599]205!--  Allocate an array of type arraydef for all parent processes to store
206!--  information of then transfer array
[1896]207     DO  i = 1, me%inter_npes
208        ALLOCATE( me%pes(i)%array_list(pmc_max_array) )
209     ENDDO
[1762]210
[1933]211 END SUBROUTINE pmc_childinit
[1762]212
213
214
[2801]215 SUBROUTINE pmc_set_dataarray_name( parentarraydesc, parentarrayname,          &
[1933]216                                    childarraydesc, childarrayname, istat )
[1762]217
[1896]218    IMPLICIT NONE
[1762]219
[1933]220    CHARACTER(LEN=*), INTENT(IN) ::  parentarrayname  !<
221    CHARACTER(LEN=*), INTENT(IN) ::  parentarraydesc  !<
222    CHARACTER(LEN=*), INTENT(IN) ::  childarrayname   !<
223    CHARACTER(LEN=*), INTENT(IN) ::  childarraydesc   !<
[1762]224
[2801]225    INTEGER(iwp), INTENT(OUT) ::  istat  !<
[1896]226!
227!-- Local variables
228    TYPE(da_namedef) ::  myname  !<
[1762]229
[2801]230    INTEGER(iwp) ::  mype  !<
[1762]231
232
[1896]233    istat = pmc_status_ok
234!
235!-- Check length of array names
[2801]236    IF ( LEN( TRIM( parentarrayname) ) > da_namelen  .OR.                      &
[1933]237         LEN( TRIM( childarrayname) ) > da_namelen )  THEN
[1896]238       istat = pmc_da_name_err
239    ENDIF
[1762]240
[1896]241    IF ( m_model_rank == 0 )  THEN
242       myindex = myindex + 1
243       myname%couple_index = myIndex
[1933]244       myname%parentdesc   = TRIM( parentarraydesc )
245       myname%nameonparent = TRIM( parentarrayname )
246       myname%childdesc    = TRIM( childarraydesc )
247       myname%nameonchild  = TRIM( childarrayname )
[1896]248    ENDIF
[1762]249
[1896]250!
[2599]251!-- Broadcast to all child processes
[2801]252!
253!-- The complete description of an transfer names array is broadcasted
254
[1896]255    CALL pmc_bcast( myname%couple_index, 0, comm=m_model_comm )
[1933]256    CALL pmc_bcast( myname%parentdesc,   0, comm=m_model_comm )
257    CALL pmc_bcast( myname%nameonparent, 0, comm=m_model_comm )
258    CALL pmc_bcast( myname%childdesc,    0, comm=m_model_comm )
259    CALL pmc_bcast( myname%nameonchild,  0, comm=m_model_comm )
[1896]260!
[2599]261!-- Broadcast to all parent processes
[2801]262!-- The complete description of an transfer array names is broadcasted als to all parent processe
263!   Only the root PE of the broadcasts to parent using intra communicator
264
[1896]265    IF ( m_model_rank == 0 )  THEN
266        mype = MPI_ROOT
267    ELSE
268        mype = MPI_PROC_NULL
269    ENDIF
[1762]270
[1933]271    CALL pmc_bcast( myname%couple_index, mype, comm=m_to_parent_comm )
272    CALL pmc_bcast( myname%parentdesc,   mype, comm=m_to_parent_comm )
273    CALL pmc_bcast( myname%nameonparent, mype, comm=m_to_parent_comm )
274    CALL pmc_bcast( myname%childdesc,    mype, comm=m_to_parent_comm )
275    CALL pmc_bcast( myname%nameonchild,  mype, comm=m_to_parent_comm )
[1762]276
[1933]277    CALL pmc_g_setname( me, myname%couple_index, myname%nameonchild )
[1762]278
[1896]279 END SUBROUTINE pmc_set_dataarray_name
[1762]280
281
282
[1896]283 SUBROUTINE pmc_set_dataarray_name_lastentry( lastentry )
[1762]284
[1896]285    IMPLICIT NONE
[1762]286
[1896]287    LOGICAL, INTENT(IN), OPTIONAL ::  lastentry  !<
288!
289!-- Local variables
290    INTEGER ::  mype  !<
291    TYPE(dA_namedef) ::  myname  !<
[1762]292
[1896]293    myname%couple_index = -1
[1762]294
[1896]295    IF ( m_model_rank == 0 )  THEN
296       mype = MPI_ROOT
297    ELSE
298       mype = MPI_PROC_NULL
299    ENDIF
[1762]300
[1933]301    CALL pmc_bcast( myname%couple_index, mype, comm=m_to_parent_comm )
[1762]302
[1896]303 END SUBROUTINE pmc_set_dataarray_name_lastentry
[1762]304
305
306
[1896]307 SUBROUTINE pmc_c_get_2d_index_list
[1762]308
[1896]309    IMPLICIT NONE
[1762]310
[2801]311    INTEGER(iwp) :: dummy               !<
312    INTEGER(iwp) :: i, ierr, i2, j, nr  !<
313    INTEGER(iwp) :: indwin              !< MPI window object
314    INTEGER(iwp) :: indwin2             !< MPI window object
[1779]315
[1896]316    INTEGER(KIND=MPI_ADDRESS_KIND) :: win_size !< Size of MPI window 1 (in bytes)
317    INTEGER(KIND=MPI_ADDRESS_KIND) :: disp     !< Displacement unit (Integer = 4, floating poit = 8
318    INTEGER(KIND=MPI_ADDRESS_KIND) :: winsize  !< Size of MPI window 2 (in bytes)
[1779]319
[1896]320    INTEGER, DIMENSION(me%inter_npes*2) :: nrele  !< Number of Elements of a
321                                                  !< horizontal slice
322    INTEGER, DIMENSION(:), POINTER ::  myind  !<
[1779]323
[1896]324    TYPE(pedef), POINTER ::  ape  !> Pointer to pedef structure
[1762]325
326
[2809]327    win_size = STORAGE_SIZE( dummy )/8
[2801]328    CALL MPI_WIN_CREATE( dummy, win_size, iwp, MPI_INFO_NULL, me%intra_comm,   &
[1896]329                         indwin, ierr )
330!
[2801]331!-- Close window on child side and open on parent side
[1896]332    CALL MPI_WIN_FENCE( 0, indwin, ierr )
[2801]333
334!   Between the two MPI_WIN_FENCE calls, the parent can fill the RMA window
335
[1933]336!-- Close window on parent side and open on child side
[2801]337
[1896]338    CALL MPI_WIN_FENCE( 0, indwin, ierr )
[1762]339
[1896]340    DO  i = 1, me%inter_npes
341       disp = me%model_rank * 2
[2801]342       CALL MPI_GET( nrele((i-1)*2+1), 2, MPI_INTEGER, i-1, disp, 2,           &
[1896]343                     MPI_INTEGER, indwin, ierr )
344    ENDDO
345!
346!-- MPI_GET is non-blocking -> data in nrele is not available until MPI_FENCE is
347!-- called
348    CALL MPI_WIN_FENCE( 0, indwin, ierr )
349!
350!-- Allocate memory for index array
351    winsize = 0
352    DO  i = 1, me%inter_npes
353       ape => me%pes(i)
354       i2 = ( i-1 ) * 2 + 1
355       nr = nrele(i2+1)
356       IF ( nr > 0 )  THEN
357          ALLOCATE( ape%locind(nr) )
358       ELSE
359          NULLIFY( ape%locind )
360       ENDIF
361       winsize = MAX( nr, winsize )
362    ENDDO
[1762]363
[1896]364    ALLOCATE( myind(2*winsize) )
365    winsize = 1
366!
367!-- Local buffer used in MPI_GET can but must not be inside the MPI Window.
[2599]368!-- Here, we use a dummy for the MPI window because the parent processes do
369!-- not access the RMA window via MPI_GET or MPI_PUT
[2801]370    CALL MPI_WIN_CREATE( dummy, winsize, iwp, MPI_INFO_NULL, me%intra_comm,    &
[1896]371                         indwin2, ierr )
372!
373!-- MPI_GET is non-blocking -> data in nrele is not available until MPI_FENCE is
374!-- called
[2801]375
[1896]376    CALL MPI_WIN_FENCE( 0, indwin2, ierr )
[2801]377
378!   Between the two MPI_WIN_FENCE calls, the parent can fill the RMA window
379
[1896]380    CALL MPI_WIN_FENCE( 0, indwin2, ierr )
[1779]381
[1896]382    DO  i = 1, me%inter_npes
383       ape => me%pes(i)
384       nr = nrele(i*2)
385       IF ( nr > 0 )  THEN
386          disp = nrele(2*(i-1)+1)
387          CALL MPI_WIN_LOCK( MPI_LOCK_SHARED , i-1, 0, indwin2, ierr )
[2801]388          CALL MPI_GET( myind, 2*nr, MPI_INTEGER, i-1, disp, 2*nr,             &
[1896]389                        MPI_INTEGER, indwin2, ierr )
390          CALL MPI_WIN_UNLOCK( i-1, indwin2, ierr )
391          DO  j = 1, nr
392             ape%locind(j)%i = myind(2*j-1)
393             ape%locind(j)%j = myind(2*j)
394          ENDDO
395          ape%nrele = nr
396       ELSE
397          ape%nrele = -1
398       ENDIF
399    ENDDO
400!
401!-- Don't know why, but this barrier is necessary before we can free the windows
402    CALL MPI_BARRIER( me%intra_comm, ierr )
[1779]403
[1896]404    CALL MPI_WIN_FREE( indWin,  ierr )
405    CALL MPI_WIN_FREE( indwin2, ierr )
406    DEALLOCATE( myind )
[1762]407
[1896]408 END SUBROUTINE pmc_c_get_2d_index_list
[1762]409
[1779]410
411
[1896]412 SUBROUTINE pmc_c_clear_next_array_list
[1762]413
[1896]414    IMPLICIT NONE
[1762]415
[1896]416    next_array_in_list = 0
[1762]417
[1896]418 END SUBROUTINE pmc_c_clear_next_array_list
[1762]419
420
[1779]421
[1896]422 LOGICAL FUNCTION pmc_c_getnextarray( myname )
[1933]423
[1896]424!
425!--  List handling is still required to get minimal interaction with
426!--  pmc_interface
427     CHARACTER(LEN=*), INTENT(OUT) ::  myname  !<
428!
429!-- Local variables
430    TYPE(pedef), POINTER    :: ape
431    TYPE(arraydef), POINTER :: ar
[1779]432
433
[1896]434    next_array_in_list = next_array_in_list + 1
435!
[2599]436!-- Array names are the same on all child PEs, so take first process to
437!-- get the name   
[1896]438    ape => me%pes(1)
439!
440!-- Check if all arrays have been processed
441    IF ( next_array_in_list > ape%nr_arrays )  THEN
442       pmc_c_getnextarray = .FALSE.
443       RETURN
444    ENDIF
[1762]445
[1896]446    ar => ape%array_list( next_array_in_list )
[1762]447
[1896]448    myname = ar%name
449!
[2801]450!-- Return true if annother array
451!-- If all array have been processed, the RETURN statement a couple of lines above is active
452
[1896]453    pmc_c_getnextarray = .TRUE.
[1762]454
[2801]455 END FUNCTION pmc_c_getnextarray
[1764]456
[1762]457
[1786]458
[1896]459 SUBROUTINE pmc_c_set_dataarray_2d( array )
[1762]460
[1896]461    IMPLICIT NONE
[1762]462
[1896]463    REAL(wp), INTENT(IN) , DIMENSION(:,:), POINTER ::  array  !<
[1762]464
[2801]465    INTEGER(iwp)               ::  i       !<
466    INTEGER(iwp)               ::  nrdims  !<
467    INTEGER(iwp), DIMENSION(4) ::  dims    !<
[1786]468
[1896]469    TYPE(C_PTR)             ::  array_adr
470    TYPE(arraydef), POINTER ::  ar
471    TYPE(pedef), POINTER    ::  ape
[1762]472
473
[1896]474    dims    = 1
475    nrdims  = 2
476    dims(1) = SIZE( array, 1 )
477    dims(2) = SIZE( array, 2 )
[1762]478
[1896]479    array_adr = C_LOC( array )
[1786]480
[1896]481    DO  i = 1, me%inter_npes
482       ape => me%pes(i)
483       ar  => ape%array_list(next_array_in_list)
484       ar%nrdims = nrdims
[2801]485       ar%dimkey = nrdims
[1896]486       ar%a_dim  = dims
487       ar%data   = array_adr
488    ENDDO
[1786]489
[1896]490 END SUBROUTINE pmc_c_set_dataarray_2d
[1786]491
[2801]492 SUBROUTINE pmc_c_set_dataarray_ip2d( array )
[1786]493
[2801]494    IMPLICIT NONE
[1786]495
[2801]496    INTEGER(idp), INTENT(IN) , DIMENSION(:,:), POINTER ::  array  !<
497
498    INTEGER(iwp)               ::  i       !<
499    INTEGER(iwp)               ::  nrdims  !<
500    INTEGER(iwp), DIMENSION(4) ::  dims    !<
501
502    TYPE(C_PTR)             ::  array_adr
503    TYPE(arraydef), POINTER ::  ar
504    TYPE(pedef), POINTER    ::  ape
505
506    dims    = 1
507    nrdims  = 2
508    dims(1) = SIZE( array, 1 )
509    dims(2) = SIZE( array, 2 )
510
511    array_adr = C_LOC( array )
512
513    DO  i = 1, me%inter_npes
514       ape => me%pes(i)
515       ar  => ape%array_list(next_array_in_list)
516       ar%nrdims = nrdims
517       ar%dimkey = 22
518       ar%a_dim  = dims
519       ar%data   = array_adr
520    ENDDO
521
522 END SUBROUTINE pmc_c_set_dataarray_ip2d
523
[1896]524 SUBROUTINE pmc_c_set_dataarray_3d (array)
[1786]525
[1896]526    IMPLICIT NONE
[1786]527
[1896]528    REAL(wp), INTENT(IN), DIMENSION(:,:,:), POINTER ::  array  !<
[1786]529
[2801]530    INTEGER(iwp)                ::  i
531    INTEGER(iwp)                ::  nrdims
532    INTEGER(iwp), DIMENSION (4) ::  dims
533   
[1896]534    TYPE(C_PTR)             ::  array_adr
535    TYPE(pedef), POINTER    ::  ape
536    TYPE(arraydef), POINTER ::  ar
[1786]537
538
[1896]539    dims    = 1
540    nrdims  = 3
541    dims(1) = SIZE( array, 1 )
542    dims(2) = SIZE( array, 2 )
543    dims(3) = SIZE( array, 3 )
[1786]544
[1896]545    array_adr = C_LOC( array )
[1786]546
[1896]547    DO  i = 1, me%inter_npes
548       ape => me%pes(i)
549       ar  => ape%array_list(next_array_in_list)
550       ar%nrdims = nrdims
[2801]551       ar%dimkey = nrdims
[1896]552       ar%a_dim  = dims
553       ar%data   = array_adr
554    ENDDO
[1786]555
[1896]556 END SUBROUTINE pmc_c_set_dataarray_3d
[1762]557
558
559
[1896]560 SUBROUTINE pmc_c_setind_and_allocmem
[1762]561
[1896]562    IMPLICIT NONE
[1933]563
[1896]564!
[1933]565!-- Naming convention for appendices:  _pc  -> parent to child transfer
566!--                                    _cp  -> child to parent transfer
567!--                                    recv -> parent to child transfer
568!--                                    send -> child to parent transfer
[2801]569    INTEGER(iwp) ::  arlen    !<
570    INTEGER(iwp) ::  myindex  !<
571    INTEGER(iwp) ::  i        !<
572    INTEGER(iwp) ::  ierr     !<
573    INTEGER(iwp) ::  istat    !<
574    INTEGER(iwp) ::  j        !<
575    INTEGER(iwp) ::  rcount   !<
576    INTEGER(iwp) ::  tag      !<
[1762]577
[2801]578    INTEGER(iwp), PARAMETER ::  noindex = -1  !<
[1762]579
[1896]580    INTEGER(idp)                   ::  bufsize  !< size of MPI data window
581    INTEGER(KIND=MPI_ADDRESS_KIND) ::  winsize  !<
[1762]582
[2801]583    INTEGER(iwp),DIMENSION(1024) ::  req  !<
[1779]584
[1933]585    REAL(wp), DIMENSION(:), POINTER, SAVE ::  base_array_pc  !< base array
586    REAL(wp), DIMENSION(:), POINTER, SAVE ::  base_array_cp  !< base array
[1762]587
[1896]588    TYPE(pedef), POINTER    ::  ape       !<
589    TYPE(arraydef), POINTER ::  ar        !<
590    Type(C_PTR)             ::  base_ptr  !<
[1779]591
[1762]592
[1896]593    myindex = 0
594    bufsize = 8
[1797]595!
[1933]596!-- Parent to child direction.
[1896]597!-- First stride: compute size and set index
598    DO  i = 1, me%inter_npes
599       ape => me%pes(i)
600       tag = 200
601       DO  j = 1, ape%nr_arrays
602          ar => ape%array_list(j)
603!
[1933]604!--       Receive index from child
[1896]605          tag = tag + 1
[2801]606          CALL MPI_RECV( myindex, 1, MPI_INTEGER, i-1, tag, me%inter_comm,     &
[1896]607                         MPI_STATUS_IGNORE, ierr )
608          ar%recvindex = myindex
609!
[1933]610!--       Determine max, because child buffer is allocated only once
[2801]611!--       All 2D and 3d arrays use the same buffer
612
613          IF ( ar%nrdims == 3 )  THEN
[1896]614             bufsize = MAX( bufsize, ar%a_dim(1)*ar%a_dim(2)*ar%a_dim(3) )
615          ELSE
616             bufsize = MAX( bufsize, ar%a_dim(1)*ar%a_dim(2) )
617          ENDIF
618       ENDDO
619    ENDDO
[1779]620!
[1896]621!-- Create RMA (one sided communication) data buffer.
622!-- The buffer for MPI_GET can be PE local, i.e. it can but must not be part of
623!-- the MPI RMA window
[1933]624    CALL pmc_alloc_mem( base_array_pc, bufsize, base_ptr )
[1896]625    me%totalbuffersize = bufsize*wp  ! total buffer size in byte
626!
627!-- Second stride: set buffer pointer
628    DO  i = 1, me%inter_npes
629       ape => me%pes(i)
630       DO  j = 1, ape%nr_arrays
631          ar => ape%array_list(j)
632          ar%recvbuf = base_ptr
633       ENDDO
634    ENDDO
635!
[1933]636!-- Child to parent direction
[1896]637    myindex = 1
638    rcount  = 0
639    bufsize = 8
[1762]640
[1896]641    DO  i = 1, me%inter_npes
642       ape => me%pes(i)
643       tag = 300
644       DO  j = 1, ape%nr_arrays
645          ar => ape%array_list(j)
[2801]646          IF ( ar%nrdims == 2 )  THEN
[1896]647             arlen = ape%nrele
648          ELSEIF( ar%nrdims == 3 )  THEN
649             arlen = ape%nrele*ar%a_dim(1)
650          ENDIF
651          tag    = tag + 1
652          rcount = rcount + 1
653          IF ( ape%nrele > 0 )  THEN
[2801]654             CALL MPI_ISEND( myindex, 1, MPI_INTEGER, i-1, tag, me%inter_comm, &
[1896]655                             req(rcount), ierr )
656             ar%sendindex = myindex
657          ELSE
[2801]658             CALL MPI_ISEND( noindex, 1, MPI_INTEGER, i-1, tag, me%inter_comm, &
[1896]659                             req(rcount), ierr )
660             ar%sendindex = noindex
661          ENDIF
662!
[2801]663!--       Maximum of 1024 pending requests
664!         1024 is an arbitrary value just to make sure the number of pending
665!         requests is getting too large. It is possible that this value has to
666!         be adjusted in case of running the model on large number of cores.
667
[1896]668          IF ( rcount == 1024 )  THEN
669             CALL MPI_WAITALL( rcount, req, MPI_STATUSES_IGNORE, ierr )
670             rcount = 0
671          ENDIF
[1762]672
[1896]673          IF ( ape%nrele > 0 )  THEN
674             ar%sendsize = arlen
675             myindex     = myindex + arlen
676             bufsize     = bufsize + arlen
677          ENDIF
[1762]678
[1896]679       ENDDO
[1762]680
[1896]681       IF ( rcount > 0 )  THEN
682          CALL MPI_WAITALL( rcount, req, MPI_STATUSES_IGNORE, ierr )
683       ENDIF
[1762]684
[1896]685    ENDDO
686!
[1933]687!-- Create RMA (one sided communication) window for data buffer child to parent
[1896]688!-- transfer.
689!-- The buffer of MPI_GET (counter part of transfer) can be PE-local, i.e. it
690!-- can but must not be part of the MPI RMA window. Only one RMA window is
691!-- required to prepare the data
[1933]692!--        for parent -> child transfer on the parent side
[1896]693!-- and
[1933]694!--        for child -> parent transfer on the child side
695    CALL pmc_alloc_mem( base_array_cp, bufsize )
[1896]696    me%totalbuffersize = bufsize * wp  ! total buffer size in byte
697
698    winSize = me%totalbuffersize
699
[2801]700    CALL MPI_WIN_CREATE( base_array_cp, winsize, wp, MPI_INFO_NULL,            &
[1933]701                         me%intra_comm, me%win_parent_child, ierr )
702    CALL MPI_WIN_FENCE( 0, me%win_parent_child, ierr )
[1896]703    CALL MPI_BARRIER( me%intra_comm, ierr )
704!
705!-- Second stride: set buffer pointer
706    DO  i = 1, me%inter_npes
707       ape => me%pes(i)
708       DO  j = 1, ape%nr_arrays
[2599]709          ar => ape%array_list(j)         
[1896]710          IF ( ape%nrele > 0 )  THEN
[1933]711             ar%sendbuf = C_LOC( base_array_cp(ar%sendindex) )
712!
[1896]713!--          TODO: if this is an error to be really expected, replace the
714!--                following message by a meaningful standard PALM message using
715!--                the message-routine
716             IF ( ar%sendindex+ar%sendsize > bufsize )  THEN
[2801]717                WRITE( 0,'(a,i4,4i7,1x,a)') 'Child buffer too small ', i,      &
718                          ar%sendindex, ar%sendsize, ar%sendindex+ar%sendsize, &
[1896]719                          bufsize, TRIM( ar%name )
720                CALL MPI_ABORT( MPI_COMM_WORLD, istat, ierr )
721             ENDIF
722          ENDIF
723       ENDDO
724    ENDDO
725
726 END SUBROUTINE pmc_c_setind_and_allocmem
727
728
729
[2801]730 SUBROUTINE pmc_c_getbuffer( waittime, particle_transfer )
[1896]731
732    IMPLICIT NONE
733
734    REAL(wp), INTENT(OUT), OPTIONAL ::  waittime  !<
[2801]735    LOGICAL, INTENT(IN), OPTIONAL   ::  particle_transfer  !<
[1896]736
[2801]737    LOGICAL                        ::  lo_ptrans!<
738   
739    INTEGER(iwp)                        ::  ierr    !<
740    INTEGER(iwp)                        ::  ij      !<
741    INTEGER(iwp)                        ::  ip      !<
742    INTEGER(iwp)                        ::  j       !<
743    INTEGER(iwp)                        ::  myindex !<
744    INTEGER(iwp)                        ::  nr      !< number of elements to get
745                                                    !< from parent
[1896]746    INTEGER(KIND=MPI_ADDRESS_KIND) ::  target_disp
747    INTEGER,DIMENSION(1)           ::  buf_shape
748
749    REAL(wp)                            ::  t1
750    REAL(wp)                            ::  t2
751
752    REAL(wp), POINTER, DIMENSION(:)     ::  buf
753    REAL(wp), POINTER, DIMENSION(:,:)   ::  data_2d
754    REAL(wp), POINTER, DIMENSION(:,:,:) ::  data_3d
755    TYPE(pedef), POINTER                ::  ape
756    TYPE(arraydef), POINTER             ::  ar
[2801]757    INTEGER(idp), POINTER, DIMENSION(:)     ::  ibuf      !<
758    INTEGER(idp), POINTER, DIMENSION(:,:)   ::  idata_2d  !<
[1896]759
760!
[1933]761!-- Synchronization of the model is done in pmci_synchronize.
762!-- Therefore the RMA window can be filled without
[1896]763!-- sychronization at this point and a barrier is not necessary.
[2801]764
765!-- In case waittime is present, the following barrier is necessary to
766!-- insure the same number of barrier calls on parent and child
767!-- This means, that here on child side two barriers are call successively
768!-- The parent is filling its buffer between the two barrier calls
769
[1896]770!-- Please note that waittime has to be set in pmc_s_fillbuffer AND
771!-- pmc_c_getbuffer
772    IF ( PRESENT( waittime ) )  THEN
773       t1 = pmc_time()
774       CALL MPI_BARRIER( me%intra_comm, ierr )
775       t2 = pmc_time()
776       waittime = t2 - t1
777    ENDIF
[2801]778
779    lo_ptrans = .FALSE.
780    IF ( PRESENT( particle_transfer))    lo_ptrans = particle_transfer
781
[1896]782!
[1933]783!-- Wait for buffer is filled.
[2801]784!
785!-- The parent side (in pmc_s_fillbuffer) is filling the buffer in the MPI RMA window
786!-- When the filling is complet, a MPI_BARRIER is called.
787!-- The child is not allowd to access the parent-buffer before it is completely filled
788!-- therefore the following barrier is required.
789
[1896]790    CALL MPI_BARRIER( me%intra_comm, ierr )
791
792    DO  ip = 1, me%inter_npes
793       ape => me%pes(ip)
794       DO  j = 1, ape%nr_arrays
795          ar => ape%array_list(j)
[2801]796
797          IF ( ar%dimkey == 2 .AND. .NOT.lo_ptrans)  THEN
[1896]798             nr = ape%nrele
[2801]799          ELSEIF ( ar%dimkey == 3 .AND. .NOT.lo_ptrans)  THEN
[1896]800             nr = ape%nrele * ar%a_dim(1)
[2801]801          ELSE IF ( ar%dimkey == 22 .AND. lo_ptrans)  THEN
802             nr = ape%nrele
803          ELSE
804             CYCLE                    ! Particle array ar not transferd here
[1896]805          ENDIF
806          buf_shape(1) = nr
[2801]807          IF ( lo_ptrans )   THEN
808             CALL C_F_POINTER( ar%recvbuf, ibuf, buf_shape )
809          ELSE
810             CALL C_F_POINTER( ar%recvbuf, buf, buf_shape )
811          ENDIF
[1896]812!
813!--       MPI passive target RMA
[2801]814!--       One data array is fetcht from MPI RMA window on parent
815
[1896]816          IF ( nr > 0 )  THEN
817             target_disp = ar%recvindex - 1
[2801]818             CALL MPI_WIN_LOCK( MPI_LOCK_SHARED , ip-1, 0,                     &
[1933]819                                me%win_parent_child, ierr )
[2801]820             IF ( lo_ptrans )   THEN
821                CALL MPI_GET( ibuf, nr*8, MPI_BYTE, ip-1, target_disp, nr*8, MPI_BYTE,  &               !There is no MPI_INTEGER8 datatype
822                                   me%win_parent_child, ierr )
823             ELSE
824                CALL MPI_GET( buf, nr, MPI_REAL, ip-1, target_disp, nr,        &
825                              MPI_REAL, me%win_parent_child, ierr )
826             ENDIF
[1933]827             CALL MPI_WIN_UNLOCK( ip-1, me%win_parent_child, ierr )
[1896]828          ENDIF
829          myindex = 1
[2801]830          IF ( ar%dimkey == 2 .AND. .NOT.lo_ptrans)  THEN
831
[1896]832             CALL C_F_POINTER( ar%data, data_2d, ar%a_dim(1:2) )
833             DO  ij = 1, ape%nrele
834                data_2d(ape%locind(ij)%j,ape%locind(ij)%i) = buf(myindex)
835                myindex = myindex + 1
836             ENDDO
[2801]837
838          ELSEIF ( ar%dimkey == 3 .AND. .NOT.lo_ptrans)  THEN
839
[1896]840             CALL C_F_POINTER( ar%data, data_3d, ar%a_dim(1:3) )
841             DO  ij = 1, ape%nrele
[2801]842                data_3d(:,ape%locind(ij)%j,ape%locind(ij)%i) =                 &
[1896]843                                              buf(myindex:myindex+ar%a_dim(1)-1)
844                myindex = myindex+ar%a_dim(1)
845             ENDDO
[2801]846
847          ELSEIF ( ar%dimkey == 22 .AND. lo_ptrans)  THEN
848             CALL C_F_POINTER( ar%data, idata_2d, ar%a_dim(1:2) )
849
850             DO  ij = 1, ape%nrele
851                idata_2d(ape%locind(ij)%j,ape%locind(ij)%i) = ibuf(myindex)
852                myindex = myindex + 1
853             ENDDO
854
[1896]855          ENDIF
856       ENDDO
857    ENDDO
858
859 END SUBROUTINE pmc_c_getbuffer
860
861
862
[2801]863 SUBROUTINE pmc_c_putbuffer( waittime , particle_transfer )
[1896]864
865    IMPLICIT NONE
866
867    REAL(wp), INTENT(OUT), OPTIONAL ::  waittime  !<
[2801]868    LOGICAL, INTENT(IN), OPTIONAL   ::  particle_transfer  !<
[1896]869
[2801]870    LOGICAL ::  lo_ptrans!<
871   
872    INTEGER(iwp) ::  ierr         !<
873    INTEGER(iwp) ::  ij           !<
874    INTEGER(iwp) ::  ip           !<
875    INTEGER(iwp) ::  j            !<
876    INTEGER(iwp) ::  myindex      !<
[1896]877
[2801]878    INTEGER(iwp), DIMENSION(1) ::  buf_shape    !<
[1896]879
880    REAL(wp) ::  t1  !<
881    REAL(wp) ::  t2  !<
882
[2801]883    REAL(wp), POINTER, DIMENSION(:)         ::  buf      !<
884    REAL(wp), POINTER, DIMENSION(:,:)       ::  data_2d  !<
885    REAL(wp), POINTER, DIMENSION(:,:,:)     ::  data_3d  !<
886   
887    INTEGER(idp), POINTER, DIMENSION(:)     ::  ibuf      !<
888    INTEGER(idp), POINTER, DIMENSION(:,:)   ::  idata_2d  !<
[1896]889
[2801]890    TYPE(pedef), POINTER                    ::  ape  !<
891    TYPE(arraydef), POINTER                 ::  ar   !<
[1896]892
893!
894!-- Wait for empty buffer
[2801]895!-- Switch RMA epoche
896
[1896]897    t1 = pmc_time()
898    CALL MPI_BARRIER( me%intra_comm, ierr )
899    t2 = pmc_time()
900    IF ( PRESENT( waittime ) )  waittime = t2 - t1
901
[2801]902    lo_ptrans = .FALSE.
903    IF ( PRESENT( particle_transfer))    lo_ptrans = particle_transfer
904
[1896]905    DO  ip = 1, me%inter_npes
906       ape => me%pes(ip)
907       DO  j = 1, ape%nr_arrays
908          ar => aPE%array_list(j)
909          myindex = 1
[2801]910
911          IF ( ar%dimkey == 2 .AND. .NOT.lo_ptrans )  THEN
912
[1896]913             buf_shape(1) = ape%nrele
914             CALL C_F_POINTER( ar%sendbuf, buf,     buf_shape     )
915             CALL C_F_POINTER( ar%data,    data_2d, ar%a_dim(1:2) )
916             DO  ij = 1, ape%nrele
917                buf(myindex) = data_2d(ape%locind(ij)%j,ape%locind(ij)%i)
918                myindex = myindex + 1
919             ENDDO
[2801]920
921          ELSEIF ( ar%dimkey == 3 .AND. .NOT.lo_ptrans )  THEN
922
[1896]923             buf_shape(1) = ape%nrele*ar%a_dim(1)
924             CALL C_F_POINTER( ar%sendbuf, buf,     buf_shape     )
925             CALL C_F_POINTER( ar%data,    data_3d, ar%a_dim(1:3) )
926             DO  ij = 1, ape%nrele
[1933]927                buf(myindex:myindex+ar%a_dim(1)-1) =                            &
[1896]928                                    data_3d(:,ape%locind(ij)%j,ape%locind(ij)%i)
929                myindex = myindex + ar%a_dim(1)
930             ENDDO
[2801]931
932          ELSE IF ( ar%dimkey == 22 .AND. lo_ptrans)  THEN
933
934             buf_shape(1) = ape%nrele
935             CALL C_F_POINTER( ar%sendbuf, ibuf,     buf_shape     )
936             CALL C_F_POINTER( ar%data,    idata_2d, ar%a_dim(1:2) )
937
938             DO  ij = 1, ape%nrele
939                ibuf(myindex) = idata_2d(ape%locind(ij)%j,ape%locind(ij)%i)
940                myindex = myindex + 1
941             ENDDO
942
[1896]943          ENDIF
944       ENDDO
945    ENDDO
946!
947!-- Buffer is filled
[2801]948!-- Switch RMA epoche
949
[1896]950    CALL MPI_Barrier(me%intra_comm, ierr)
951
952 END SUBROUTINE pmc_c_putbuffer
953
[1764]954#endif
[1933]955 END MODULE pmc_child
Note: See TracBrowser for help on using the repository browser.