| 2 | |
| 3 | As a basis for the discussion, here's how I've currently coded NEMO (v.3.2) to use dynamic memory. |
| 4 | |
| 5 | Highest-level changes are in OPA_SRC/opa.F90 and the routine opa_init(): |
| 6 | |
| 7 | {{{ |
| 8 | #if defined key_mpp_dyndist |
| 9 | ! Decide on size of grid now that we have our communicator size |
| 10 | ! If we're not using dynamic memory then mpp_partition does nothing. |
| 11 | |
| 12 | #if defined key_mpp_mpi || defined key_mpp_shmem |
| 13 | CALL opa_partition() |
| 14 | #else |
| 15 | jpni = 1 |
| 16 | jpnj = 1 |
| 17 | jpnij = jpni*jpnj |
| 18 | #endif |
| 19 | ! Calculate domain dimensions given calculated jpi and jpj |
| 20 | jpi = ( jpiglo-2*jpreci + (jpni-1) ) / jpni + 2*jpreci !: first dim. |
| 21 | jpj = ( jpjglo-2*jprecj + (jpnj-1) ) / jpnj + 2*jprecj !: second dim. |
| 22 | jpim1 = jpi-1 !: inner domain indices |
| 23 | jpjm1 = jpj-1 !: " " |
| 24 | jpkm1 = jpk-1 !: " " |
| 25 | jpij = jpi*jpj !: jpi x j |
| 26 | |
| 27 | ! Now we know the dimensions of the grid, allocate arrays |
| 28 | CALL opa_alloc() |
| 29 | #endif |
| 30 | }}} |
| 31 | |
| 32 | The inclusion of the new code is currently controlled by the cpp key 'key_mpp_dyndist' but it would greatly improve the cleanliness of the code if we make a complete break from the static-memory version and thus can drop the use of this cpp key. My understanding of the conclusion of the meeting in Southampton was that this is what we're going to do. |
| 33 | |
| 34 | This addition to opa_init() calls two further new routines, opa_partition() and opa_alloc(): |
| 35 | {{{ |
| 36 | SUBROUTINE opa_partition |
| 37 | USE par_oce |
| 38 | IMPLICIT none |
| 39 | INTEGER, PARAMETER :: nfactmax = 20 |
| 40 | INTEGER :: nfact ! The no. of factors returned |
| 41 | INTEGER :: ierr ! Error flag |
| 42 | INTEGER :: i |
| 43 | INTEGER :: idiff, mindiff, imin ! For choosing pair of factors that are |
| 44 | ! closest in value |
| 45 | INTEGER, DIMENSION(nfactmax) :: ifact ! Array of factors |
| 46 | ierr = 0 |
| 47 | |
| 48 | #if ! defined key_mpp_dyndist |
| 49 | RETURN ! If we aren't using dynamic memory then jpnj and jpni are set |
| 50 | ! at compile time |
| 51 | #else |
| 52 | |
| 53 | CALL factorise(ifact, nfactmax, nfact, mppsize, ierr) |
| 54 | |
| 55 | IF(nfact <= 1)THEN |
| 56 | WRITE (numout, *) 'WARNING: factorisation of number of PEs failed' |
| 57 | WRITE (numout, *) ' : using grid of ',mppsize,' x 1' |
| 58 | jpnj = 1 |
| 59 | jpni = mppsize |
| 60 | ELSE |
| 61 | ! Search through factors for the pair that are closest in value |
| 62 | mindiff = 1000000 |
| 63 | imin = 1 |
| 64 | DO i=1,nfact-1,2 |
| 65 | idiff = ABS(ifact(i) - ifact(i+1)) |
| 66 | IF(idiff < mindiff)THEN |
| 67 | mindiff = idiff |
| 68 | imin = i |
| 69 | END IF |
| 70 | END DO |
| 71 | jpnj = ifact(imin) |
| 72 | jpni = ifact(imin + 1) |
| 73 | ENDIF |
| 74 | jpnij = jpni*jpnj |
| 75 | |
| 76 | WRITE(*,*) 'ARPDBG: jpni = ',jpni,'jpnj = ',jpnj,'jpnij = ',jpnij |
| 77 | |
| 78 | #endif |
| 79 | |
| 80 | END SUBROUTINE opa_partition |
| 81 | }}} |
| 82 | where ''factorise()'' returns the prime factors of its argument. |
| 83 | |