C Copyright 1981-2012 ECMWF.
C
C This software is licensed under the terms of the Apache Licence 
C Version 2.0 which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
C
C In applying this licence, ECMWF does not waive the privileges and immunities 
C granted to it by virtue of its status as an intergovernmental organisation 
C nor does it submit to any jurisdiction.
C

      INTEGER FUNCTION IRGMEM (KPR, KERR)
C
C---->
C**** *IRGMEM*
C
C     PURPOSE
C     _______
C
C     This routine acquires heap space for quasi regular to regular
C     interpolation.
C
C     INTERFACE
C     _________
C
C     IERR = IRGMEM (KPR, KERR)
C
C     Input parameters
C     ________________
C
C     KPR        - The debug print switch.
C                  0  , No debugging output.
C                  1  , Produce debugging output.
C
C     KERR       - The error control flag.
C                  -ve, No error message. Return error code.
C                  0  , Hard failure with error message.
C                  +ve, Print error message. Return error code.
C
C     Output parameters
C     ________________
C
C     None
C
C     Return value
C     ____________
C
C     The error indicator (INTEGER).
C
C     Error and Warning Return Values
C     _______________________________
C
C     None
C
C     Common block usage
C     __________________
C
C     nifld.common - This file contains all the input field
C                    definition variables.
C
C     NINS         - Number of grid points in NS direction for input
C                    field (used in grspace.h).
C     NIWE         - Number of grid points in WE direction for input
C                    field (used in grspace.h).
C
C     nofld.common - This file contains all the output field
C                    definition variables.
C
C     NONS         - Number of grid points in NS direction for output
C                    field (used in grspace.h).
C     NOWE         - Number of grid points in WE direction for output
C                    field (used in grspace.h).
C
C     grspace.h    - This file contains all the work space array
C                    definitions for grid point to grid point
C                    interpolation.
C
C     GRID_POINT
C
C     NILATGP      - POINTER to array MILATG.
C     NILONGP      - POINTER to array MILONG.
C     NILSMP       - POINTER to array MILSM.
C     NINPNTP      - POINTER to array RINPNT.
C     NISTRTP      - POINTER to array MISTRT.
C     NNSDISTP     - POINTER to array MNSDIST.
C     NNSINDP      - POINTER to array MNSIND.
C     NMAXP        - POINTER to array RMAX.
C     NOLATGP      - POINTER to array MOLATG.
C     NOLONGP      - POINTER to array MOLONG.
C     NOLSMP       - POINTER to array MOLSM.
C     NWEDISTP     - POINTER to array MWEDIST.
C     NWEINDP      - POINTER to array MWEIND.
C     NWFACTP      - POINTER to array WFACT.
C
C     MILATG       - Dynamic array of length (NINS) (see nifld.common)
C                    which holds the values of the input field
C                    latitudes.
C     MILONG       - Dynamic array of length (NIWE + 1) (see
C                    nifld.common) which holds the values of the
C                    input field longitudes.
C     MILSM        - Dynamic array of length (NIWE, 2) (see
C                    nifld.common) used in calculating the effects of
C                    the land sea mask on interpolation.
C     MISTRT       - Dynamic array of length (NINS) (see nifld.common)
C                    which holds the array offsets of the start of
C                    each latitude line for a quasi regular Gaussian
C                    input field. No space is assigned to this array
C                    for a regular input field.
C     MNSDIST      - Dynamic array of length (2, NONS) (see
C                    nofld.common) which holds the distances to
C                    neighbouring latitude lines of the input field
C                    from the associated line of latitude in the
C                    output field.
C     MNSIND       - Dynamic array of length (2, NONS) (see
C                    nofld.common) which holds the latitude line
C                    numbers (array offset) of the input field
C                    associated with each line of latitude in the
C                    output field.
C     MOLATG       - Dynamic array of length (NONS) (see nofld.common)
C                    which holds the values of the output field
C                    latitudes.
C     MOLONG       - Dynamic array of length (NOWE) (see nofld.common)
C                    which holds the values of the output field
C                    longitudes.
C     MOLSM        - Dynamic array of length (NOWE) (see nofld.common)
C                    used in calculating the effects of the land sea
C                    mask on interpolation.
C     MWEDIST      - Dynamic array of length (2, NONS) (see
C                    nofld.common) for a regular input field and of
C                    length (2, 2 * NONS * NOWE) (see nofld.common)
C                    for a quasi regular Gaussian input field. This
C                    array holds the distances to neighbouring
C                    longitude points of the input field from the
C                    associated longitude points in the output field.
C     MWEIND       - Dynamic array of length (2, NONS) (see
C                    nofld.common) for a regular input field and of
C                    length (2, 2 * NONS * NOWE) (see nofld.common)
C                    for a quasi regular Gaussian input field. This
C                    array holds the longitude points (array offset)
C                    from the input field associated with each
C                    longitude point in the output field.
C     RINPNT       - Dynamic array of length (NOWE) (see nofld.common)
C                    used to aid vectorisation in processing
C                    precipitation fields.
C     RMAX         - Dynamic array of length (NOWE) (see nofld.common)
C                    used to aid vectorisation in processing
C                    precipitation fields.
C     WFACT        - Dynamic array of length (4, NOWE * NONS) (see
C                    nofld.common) which holds the interpolation
C                    weights for each point in the output field.
C
C     EXTERNALS
C     _________
C
C     IGALLOC    - Get a heap allocation for array space.
C     INTLOG(R)  - Logs messages.
C
C     METHOD
C     ______
C
C     This routine first calculates how much heap space is required.
C     IGALLOC is then used to acquire the required space. Finally the
C     POINTERs are initialised to allow use of the dynamic arrays.
C
C     REFERENCE
C     _________
C
C     None
C
C     COMMENTS
C     ________
C
C     Program contains sections 0 to 3 and 9
C
C     AUTHOR
C     ______
C
C     K. Fielding      *ECMWF*      Jan 1994
C
C     MODIFICATIONS
C     _____________
C
C     None
C
C----<
C     -----------------------------------------------------------------|
C*    Section 0. Definition of variables.
C     -----------------------------------------------------------------|
C
      IMPLICIT NONE
C
#include "parim.h"
#include "nifld.common"
#include "nofld.common"
#include "grspace.h"
C
C     Dummy arguments
C
      INTEGER*8 WORK
      INTEGER*8 DELTA
      INTEGER*8 OFFSET

      INTEGER KPR, KERR
C
C     Local variables
C
#ifdef POINTER_64
      INTEGER*8 IBASE
#else
      INTEGER IBASE
#endif
      INTEGER IREQUEST, IERR
      INTEGER JPROUTINE
      PARAMETER (JPROUTINE = 23100)
C
C     External functions
C
      INTEGER IGALLOC
C
C     -----------------------------------------------------------------|
C*    Section 1. Initialisation
C     -----------------------------------------------------------------|
C
  100 CONTINUE
C
      IF( KPR.GE.1 ) CALL INTLOG(JP_DEBUG,'IRGMEM: Section 1.',JPQUIET)
C
      IRGMEM = 0
C
C     -----------------------------------------------------------------|
C*    Section 2. Calculate memory required and get heap
C     -----------------------------------------------------------------|
C
  200 CONTINUE
C
      IF( KPR.GE.1 ) CALL INTLOG(JP_DEBUG,'IRGMEM: Section 2.',JPQUIET)
C
C     REAL arrays (This may change for double precision version)
C
      IREQUEST = 4 * NOWE * NONS * JPRLEN
C
C     Fields for precipitation calculations
C
      IREQUEST = IREQUEST + 2 * NOWE * JPRLEN
C
C     Fixed integer fields
C
      IREQUEST = IREQUEST + (NIWE + 1 + NINS + NOWE + 5 * NONS) *
     1  JPILEN
C
C     Reduced Gaussian input fields (These change for regular fields)
C
      IREQUEST = IREQUEST + (8 * NOWE * NONS + NINS) * JPILEN
C
C     Fields for LSM calculations
C
      IREQUEST = IREQUEST + (2 * NIWE + NOWE) * JPILEN
C
C     Get the required memory
C
      IERR = IGALLOC (JPINNER, IREQUEST, IBASE, KPR, KERR)
C
      IF( IERR.GT.0 ) THEN
         IRGMEM = IERR
         GOTO 900
      ENDIF
C
C     -----------------------------------------------------------------|
C*    Section 3. Initialise base addresses for POINTER arrays
C     -----------------------------------------------------------------|
C
  300 CONTINUE
C
      IF( KPR.GE.1 ) CALL INTLOG(JP_DEBUG,'IRGMEM: Section 3.',JPQUIET)
C
C     REAL arrays first to ease conversion to DOUBLE PRECISION
C
      NWFACTP = IBASE
C
C     Precipitation REAL arrays
C
C     We are having trouble when using POINTER values in arithmetic
C     where we get overflow when we don't expect it. Like the POINTER
C     is interpreted as a 32-bit length value. For that reason we 
C     calculate an OFFSET and add DELTA values to it before reading
C     its value out into the various base addresses which are then not
C     used again in further calculations.


      OFFSET = NWFACTP + 4 * NOWE * NONS * JPRLEN
      NMAXP = OFFSET
C      NMAXP = NWFACTP + 4 * NOWE * NONS * JPRLEN

      DELTA = NOWE * JPRLEN
      OFFSET = OFFSET + DELTA
      NINPNTP = OFFSET
C      NINPNTP = NMAXP + NOWE * JPRLEN

C
C     This offset may change if DOUBLE PRECISION
C
      DELTA = NOWE * JPRLEN
      OFFSET = OFFSET + DELTA
      NILONGP = OFFSET      
C      NILONGP = NINPNTP + NOWE * JPRLEN

C
      DELTA = (NIWE + 1) * JPILEN
      OFFSET = OFFSET + DELTA
      NILATGP = OFFSET
C      NILATGP  = NILONGP + (NIWE + 1) * JPILEN

      DELTA = NINS * JPILEN
      OFFSET = OFFSET + DELTA
      NOLONGP = OFFSET
C      NOLONGP = NILATGP + NINS * JPILEN

      DELTA = NOWE * JPILEN
      OFFSET = OFFSET + DELTA
      NOLATGP = OFFSET
C      NOLATGP  = NOLONGP + NOWE * JPILEN

      DELTA = NONS * JPILEN
      OFFSET = OFFSET + DELTA
      NNSINDP = OFFSET      
C      NNSINDP = NOLATGP + NONS * JPILEN

      DELTA = 2 * NONS * JPILEN
      OFFSET = OFFSET + DELTA
      NNSDISTP = OFFSET
C      NNSDISTP = NNSINDP + 2 * NONS * JPILEN

C
      DELTA = 2 * NONS * JPILEN
      OFFSET = OFFSET + DELTA
      NWEINDP = OFFSET
C      NWEINDP = NNSDISTP  + 2 * NONS * JPILEN

      DELTA = 4 * NOWE * NONS * JPILEN
      OFFSET = OFFSET + DELTA
      NWEDISTP = OFFSET
C      NWEDISTP = NWEINDP + 4 * NOWE * NONS * JPILEN
      
      DELTA = 4 * NOWE * NONS * JPILEN
      OFFSET = OFFSET + DELTA
      NISTRTP = OFFSET
C      NISTRTP  = NWEDISTP + 4 * NOWE * NONS * JPILEN

C
C     LSM arrays
C
      DELTA = NINS * JPILEN
      OFFSET = OFFSET + DELTA
      NILSMP = OFFSET
c      NILSMP = NISTRTP + NINS * JPILEN

      DELTA = 2 * NIWE * JPILEN
      OFFSET = OFFSET + DELTA
      NOLSMP = OFFSET
c      NOLSMP = NILSMP + 2 * NIWE * JPILEN
         
C
      IF( KPR.GE.1 ) THEN
        CALL INTLOG(JP_DEBUG,'IRGMEM: ************************',JPQUIET)
        CALL INTLOG(JP_DEBUG,'IRGMEM: * Some address values',JPQUIET)
        CALL INTLOG(JP_DEBUG,'IRGMEM: * may display overflowed',JPQUIET)
        CALL INTLOG(JP_DEBUG,'IRGMEM: * when printed to screen',JPQUIET)
        CALL INTLOG(JP_DEBUG,'IRGMEM: ************************',JPQUIET)
        CALL INTLOG(JP_DEBUG,'IRGMEM: Output base addresses.',JPQUIET)
        CALL INTLOG(JP_DEBUG,'IRGMEM: WFACT address = ',NWFACTP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: RMAX address = ',NMAXP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: RINPNT address = ',NINPNTP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: Input long.address = ',NILONGP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: Input lat.address = ',NILATGP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: Output long.address = ',NOLONGP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: Output lat.address = ',NOLATGP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: NS offset address = ',NNSINDP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: NS distance address = ',NNSDISTP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: WE offset address = ',NWEINDP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: WE distance address = ',NWEDISTP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: Line start array addr.= ',NISTRTP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: Input LSM address = ',NILSMP)
        CALL INTLOG(JP_DEBUG,'IRGMEM: Output LSM address = ',NOLSMP)
        
      ENDIF
C

C     -----------------------------------------------------------------|
C*    Section 9. Return to calling routine. Format statements
C     -----------------------------------------------------------------|
C
  900 CONTINUE
C
      IF( KPR.GE.1 ) CALL INTLOG(JP_DEBUG,'IRGMEM: Section 9.',JPQUIET)
C
      RETURN
      END
