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

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

messed document changes for r3932 cleaned up

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