! (C) Copyright 2001- ECMWF. ! (C) Copyright 2001- Meteo-France. ! ! This software is licensed under the terms of the Apache Licence Version 2.0 ! which can be obtained at http://www.apache.org/licenses/LICENSE-2.0. ! In applying this licence, ECMWF does not waive the privileges and immunities ! granted to it by virtue of its status as an intergovernmental organisation ! nor does it submit to any jurisdiction. MODULE ECTRANS_FIELD_VIEW_MOD ! Must stay precision independent (i.e. do not use parkind or JPRB) USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR, C_INT, C_INTPTR_T, C_LOC, C_F_POINTER, C_FLOAT, C_DOUBLE, C_NULL_PTR USE ABORT_TRANS_MOD, ONLY : ABORT_TRANS IMPLICIT NONE PRIVATE PUBLIC :: FIELD_VIEW, FIELD_VIEW_INIT, FIELD_VIEW_SET_DATA_PTR, FIELD_VIEW_GET_DATA_PTR PUBLIC :: FIELD_VIEW_SET_IVSET_PTR, FIELD_VIEW_GET_IVSET_PTR PUBLIC :: FIELD_VIEW_SET_NAME, FIELD_VIEW_GET_NAME_PTR PUBLIC :: FIELD_VIEW_GET_EXTENT, FIELD_VIEW_GET_STRIDE, FIELD_VIEW_GET_DIM_ROLE, FIELD_VIEW_GET_EXTENT_BY_ROLE PUBLIC :: FIELD_VIEW_SET_ACCESS, FIELD_VIEW_ADD_ACCESS, FIELD_VIEW_HAS_ACCESS, FIELD_VIEW_CLEAR_ACCESS PUBLIC :: FIELD_VIEW_DIM_ROLE, FIELD_VIEW_INDEXING, FIELD_VIEW_ACCESS_TYPE, FIELD_VIEW_ACCESS INTEGER, PARAMETER :: MAX_RANK = 4 ! MEMORY ACCESS INTEGER(C_INT), PARAMETER :: & & ACCESS_UNKNOWN = 0, & & ACCESS_HOST = 1, & & ACCESS_DEVICE = 2, & & ACCESS_READONLY = 4 TYPE :: FIELD_VIEW_ACCESS_TYPE INTEGER(C_INT) :: UNKNOWN = ACCESS_UNKNOWN INTEGER(C_INT) :: HOST = ACCESS_HOST INTEGER(C_INT) :: DEVICE = ACCESS_DEVICE INTEGER(C_INT) :: READONLY = ACCESS_READONLY END TYPE FIELD_VIEW_ACCESS_TYPE TYPE(FIELD_VIEW_ACCESS_TYPE), SAVE, PROTECTED :: FIELD_VIEW_ACCESS ! DIMENSION ROLES INTEGER(C_INT), PARAMETER :: & & DIM_UNKNOWN = 0, & & DIM_NPROMA = 1, & & DIM_BLOCK = 2, & & DIM_LEVEL = 3, & & DIM_FIELD = 4, & & DIM_SPEC2 = 5 TYPE :: FIELD_VIEW_DIM_ROLE_TYPE INTEGER(C_INT) :: UNKNOWN = DIM_UNKNOWN INTEGER(C_INT) :: NPROMA = DIM_NPROMA INTEGER(C_INT) :: BLOCK = DIM_BLOCK INTEGER(C_INT) :: LEVEL = DIM_LEVEL INTEGER(C_INT) :: FIELD = DIM_FIELD INTEGER(C_INT) :: SPEC2 = DIM_SPEC2 END TYPE FIELD_VIEW_DIM_ROLE_TYPE TYPE(FIELD_VIEW_DIM_ROLE_TYPE), SAVE, PROTECTED :: FIELD_VIEW_DIM_ROLE INTEGER, PARAMETER :: DIM_ROLE_BITS = 4 ! INDEXING uses C dimension ordering. The least-significant role describes EXTENTS(1). ! C array shapes represented by the indexing values. INTEGER(C_INT), PARAMETER :: & & INDEXING_UNKNOWN = DIM_UNKNOWN, & & C_INDEXING_BLOCK = DIM_BLOCK, & ! array[NBLKS] & C_INDEXING_BLOCK_NPROMA = IOR(DIM_BLOCK, ISHFT(DIM_NPROMA, DIM_ROLE_BITS)), & ! array[NBLKS][NPROMA] & C_INDEXING_BLOCK_LEVEL_NPROMA = IOR(DIM_BLOCK, IOR(ISHFT(DIM_LEVEL, DIM_ROLE_BITS), & ! array[NBLKS][NLEVS][NPROMA] & ISHFT(DIM_NPROMA, 2 * DIM_ROLE_BITS))), & & C_INDEXING_BLOCK_FIELD_LEVEL_NPROMA = IOR(DIM_BLOCK, IOR(ISHFT(DIM_FIELD, DIM_ROLE_BITS), & ! array[NBLKS][NFIELDS][NLEVS][NPROMA] & IOR(ISHFT(DIM_LEVEL, 2 * DIM_ROLE_BITS), & & ISHFT(DIM_NPROMA, 3 * DIM_ROLE_BITS)))), & & C_INDEXING_SPEC2 = DIM_SPEC2, & ! array[NSPEC2] & C_INDEXING_SPEC2_LEVEL = IOR(DIM_SPEC2, ISHFT(DIM_LEVEL, DIM_ROLE_BITS)), & ! array[NSPEC2][NLEVS] & C_INDEXING_FIELD_SPEC2_LEVEL = IOR(DIM_FIELD, IOR(ISHFT(DIM_SPEC2, DIM_ROLE_BITS), & ! array[NFIELDS][NSPEC2][NLEVS] & ISHFT(DIM_LEVEL, 2 * DIM_ROLE_BITS))) ! Fortran array shapes represented by the C-ordered indexing values. TYPE :: FIELD_VIEW_INDEXING_TYPE INTEGER(C_INT) :: UNKNOWN = INDEXING_UNKNOWN INTEGER(C_INT) :: BLOCK = C_INDEXING_BLOCK ! ARRAY(NBLKS) INTEGER(C_INT) :: NPROMA_BLOCK = C_INDEXING_BLOCK_NPROMA ! ARRAY(NPROMA, NBLKS) INTEGER(C_INT) :: NPROMA_LEVEL_BLOCK = C_INDEXING_BLOCK_LEVEL_NPROMA ! ARRAY(NPROMA, NLEVS, NBLKS) INTEGER(C_INT) :: NPROMA_LEVEL_FIELD_BLOCK = C_INDEXING_BLOCK_FIELD_LEVEL_NPROMA ! ARRAY(NPROMA, NLEVS, NFIELDS, NBLKS) INTEGER(C_INT) :: SPEC2 = C_INDEXING_SPEC2 ! ARRAY(NSPEC2) INTEGER(C_INT) :: LEVEL_SPEC2 = C_INDEXING_SPEC2_LEVEL ! ARRAY(NLEVS, NSPEC2) INTEGER(C_INT) :: LEVEL_SPEC2_FIELD = C_INDEXING_FIELD_SPEC2_LEVEL ! ARRAY(NLEVS, NSPEC2, NFIELDS) END TYPE FIELD_VIEW_INDEXING_TYPE TYPE(FIELD_VIEW_INDEXING_TYPE), SAVE, PROTECTED :: FIELD_VIEW_INDEXING ! C-interoperable view of field data and its shape, stride, and dimension-role metadata. ! Array metadata uses C dimension ordering. Spectral fields may additionally reference ! an IVSET array assigning each level to a spectral distribution set. TYPE, BIND(C) :: FIELD_VIEW ! ARRAY TYPE(C_PTR) :: DATA INTEGER(C_INT) :: ACCESS INTEGER(C_INT) :: KIND INTEGER(C_INT) :: RANK INTEGER(C_INT) :: EXTENTS(MAX_RANK) ! C ORDERING INTEGER(C_INT) :: STRIDES(MAX_RANK) ! C ORDERING ! IVSET TYPE(C_PTR) :: IVSET ! Value indexing is specified by IVSET_BASE INTEGER(C_INT) :: IVSET_SIZE INTEGER(C_INT) :: IVSET_BASE ! 0 for zero-based values, 1 for one-based values ! NAME TYPE(C_PTR) :: NAME INTEGER(C_INT) :: NAME_SIZE ! INDEXING INTEGER(C_INT) :: INDEXING ! NOTE: C ORDERING END TYPE INTERFACE FIELD_VIEW_GET_DATA_PTR MODULE PROCEDURE :: GET_DATA_PTR_1RM, GET_DATA_PTR_2RM, GET_DATA_PTR_3RM, GET_DATA_PTR_4RM MODULE PROCEDURE :: GET_DATA_PTR_1RD, GET_DATA_PTR_2RD, GET_DATA_PTR_3RD, GET_DATA_PTR_4RD END INTERFACE INTERFACE FIELD_VIEW_SET_DATA_PTR MODULE PROCEDURE :: SET_DATA_PTR_1RM, SET_DATA_PTR_2RM, SET_DATA_PTR_3RM, SET_DATA_PTR_4RM MODULE PROCEDURE :: SET_DATA_PTR_1RD, SET_DATA_PTR_2RD, SET_DATA_PTR_3RD, SET_DATA_PTR_4RD END INTERFACE INTERFACE FIELD_VIEW_SET_ACCESS MODULE PROCEDURE :: SET_ACCESS_1, SET_ACCESS_2, SET_ACCESS_3 END INTERFACE INTERFACE FIELD_VIEW_ADD_ACCESS MODULE PROCEDURE :: ADD_ACCESS_1, ADD_ACCESS_2, ADD_ACCESS_3 END INTERFACE INTERFACE FIELD_VIEW_HAS_ACCESS MODULE PROCEDURE :: HAS_ACCESS_1, HAS_ACCESS_2, HAS_ACCESS_3 END INTERFACE CONTAINS PURE SUBROUTINE FIELD_VIEW_INIT(YLFV) TYPE(FIELD_VIEW), INTENT(OUT) :: YLFV YLFV%DATA = C_NULL_PTR YLFV%ACCESS = ACCESS_UNKNOWN YLFV%KIND = 0 YLFV%RANK = 0 YLFV%EXTENTS = 0 YLFV%STRIDES = 0 YLFV%IVSET = C_NULL_PTR YLFV%IVSET_SIZE = 0 YLFV%IVSET_BASE = 1 YLFV%NAME = C_NULL_PTR YLFV%NAME_SIZE = 0 YLFV%INDEXING = INDEXING_UNKNOWN END SUBROUTINE PURE SUBROUTINE FIELD_VIEW_CLEAR_ACCESS(YLFV) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV YLFV%ACCESS = ACCESS_UNKNOWN END SUBROUTINE PURE SUBROUTINE SET_ACCESS_1(YLFV, ACCESS1) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1 YLFV%ACCESS = ACCESS1 END SUBROUTINE PURE SUBROUTINE SET_ACCESS_2(YLFV, ACCESS1, ACCESS2) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1, ACCESS2 YLFV%ACCESS = IOR(ACCESS1, ACCESS2) END SUBROUTINE PURE SUBROUTINE SET_ACCESS_3(YLFV, ACCESS1, ACCESS2, ACCESS3) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1, ACCESS2, ACCESS3 YLFV%ACCESS = IOR(ACCESS1, IOR(ACCESS2, ACCESS3)) END SUBROUTINE PURE SUBROUTINE ADD_ACCESS_1(YLFV, ACCESS1) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1 YLFV%ACCESS = IOR(YLFV%ACCESS, ACCESS1) END SUBROUTINE PURE SUBROUTINE ADD_ACCESS_2(YLFV, ACCESS1, ACCESS2) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1, ACCESS2 YLFV%ACCESS = IOR(YLFV%ACCESS, IOR(ACCESS1, ACCESS2)) END SUBROUTINE PURE SUBROUTINE ADD_ACCESS_3(YLFV, ACCESS1, ACCESS2, ACCESS3) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1, ACCESS2, ACCESS3 YLFV%ACCESS = IOR(YLFV%ACCESS, IOR(ACCESS1, IOR(ACCESS2, ACCESS3))) END SUBROUTINE PURE FUNCTION HAS_ACCESS_1(YLFV, ACCESS1) RESULT(ENABLED) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1 LOGICAL :: ENABLED ENABLED = IAND(YLFV%ACCESS, ACCESS1) == ACCESS1 END FUNCTION PURE FUNCTION HAS_ACCESS_2(YLFV, ACCESS1, ACCESS2) RESULT(ENABLED) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1, ACCESS2 LOGICAL :: ENABLED ENABLED = IAND(YLFV%ACCESS, IOR(ACCESS1, ACCESS2)) == IOR(ACCESS1, ACCESS2) END FUNCTION PURE FUNCTION HAS_ACCESS_3(YLFV, ACCESS1, ACCESS2, ACCESS3) RESULT(ENABLED) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER(C_INT), INTENT(IN) :: ACCESS1, ACCESS2, ACCESS3 LOGICAL :: ENABLED ENABLED = IAND(YLFV%ACCESS, IOR(ACCESS1, IOR(ACCESS2, ACCESS3))) == IOR(ACCESS1, IOR(ACCESS2, ACCESS3)) END FUNCTION SUBROUTINE SET_DATA_PTR_METADATA(YLFV, DATA, KIND, RANK, FORTRAN_EXTENTS, FORTRAN_OFFSETS) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV TYPE(C_PTR), INTENT(IN) :: DATA INTEGER(C_INT), INTENT(IN) :: KIND ! bytes of data type (e.g., 4 for REAL(C_FLOAT), 8 for REAL(C_DOUBLE)) INTEGER(C_INT), INTENT(IN) :: RANK INTEGER(C_INT), INTENT(IN) :: FORTRAN_EXTENTS(RANK) INTEGER(C_INTPTR_T), INTENT(IN) :: FORTRAN_OFFSETS(RANK) INTEGER(C_INT) :: FORTRAN_STRIDES(RANK) INTEGER :: JDIM, JFIRST YLFV%DATA = DATA YLFV%KIND = KIND YLFV%RANK = RANK YLFV%EXTENTS = 0 YLFV%STRIDES = 0 IF (PRODUCT(FORTRAN_EXTENTS) == 1) THEN FORTRAN_STRIDES = 1 ELSE FORTRAN_STRIDES = 0 JFIRST = 0 DO JDIM = 1, RANK IF (FORTRAN_OFFSETS(JDIM) /= 0) THEN JFIRST = JDIM EXIT ENDIF ENDDO IF (JFIRST > 0) FORTRAN_STRIDES(1) = FORTRAN_OFFSETS(JFIRST) / KIND DO JDIM = 2, RANK IF (FORTRAN_OFFSETS(JDIM) /= 0) THEN FORTRAN_STRIDES(JDIM) = FORTRAN_OFFSETS(JDIM) / KIND ELSE FORTRAN_STRIDES(JDIM) = FORTRAN_STRIDES(JDIM-1) * FORTRAN_EXTENTS(JDIM-1) ENDIF ENDDO ENDIF DO JDIM = 1, RANK YLFV%EXTENTS(RANK-JDIM+1) = FORTRAN_EXTENTS(JDIM) YLFV%STRIDES(RANK-JDIM+1) = FORTRAN_STRIDES(JDIM) ENDDO END SUBROUTINE SUBROUTINE SET_DATA_PTR_1RM(YLFV, PTR) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV REAL(C_FLOAT), POINTER, INTENT(IN) :: PTR(:) INTEGER(C_INT), PARAMETER :: RANK = 1 INTEGER(C_INT) :: EXTENTS(RANK) INTEGER(C_INTPTR_T) :: BASE, OFFSETS(RANK) TYPE(C_PTR) :: DATA DATA = C_LOC(PTR(1)) BASE = TRANSFER(DATA, BASE) EXTENTS = SHAPE(PTR) OFFSETS = 0 IF (SIZE(PTR, 1) > 1) OFFSETS(1) = TRANSFER(C_LOC(PTR(2)), BASE) - BASE CALL SET_DATA_PTR_METADATA(YLFV, DATA, STORAGE_SIZE(PTR)/8, RANK, EXTENTS, OFFSETS) END SUBROUTINE SUBROUTINE SET_DATA_PTR_1RD(YLFV, PTR) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV REAL(C_DOUBLE), POINTER, INTENT(IN) :: PTR(:) INTEGER(C_INT), PARAMETER :: RANK = 1 INTEGER(C_INT) :: EXTENTS(RANK) INTEGER(C_INTPTR_T) :: BASE, OFFSETS(RANK) TYPE(C_PTR) :: DATA DATA = C_LOC(PTR(1)) BASE = TRANSFER(DATA, BASE) EXTENTS = SHAPE(PTR) OFFSETS = 0 IF (SIZE(PTR, 1) > 1) OFFSETS(1) = TRANSFER(C_LOC(PTR(2)), BASE) - BASE CALL SET_DATA_PTR_METADATA(YLFV, DATA, STORAGE_SIZE(PTR)/8, RANK, EXTENTS, OFFSETS) END SUBROUTINE SUBROUTINE SET_DATA_PTR_2RM(YLFV, PTR) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV REAL(C_FLOAT), POINTER, INTENT(IN) :: PTR(:,:) INTEGER(C_INT), PARAMETER :: RANK = 2 INTEGER(C_INT) :: EXTENTS(RANK) INTEGER(C_INTPTR_T) :: BASE, OFFSETS(RANK) TYPE(C_PTR) :: DATA DATA = C_LOC(PTR(1,1)) BASE = TRANSFER(DATA, BASE) EXTENTS = SHAPE(PTR) OFFSETS = 0 IF (SIZE(PTR, 1) > 1) OFFSETS(1) = TRANSFER(C_LOC(PTR(2,1)), BASE) - BASE IF (SIZE(PTR, 2) > 1) OFFSETS(2) = TRANSFER(C_LOC(PTR(1,2)), BASE) - BASE CALL SET_DATA_PTR_METADATA(YLFV, DATA, STORAGE_SIZE(PTR)/8, RANK, EXTENTS, OFFSETS) END SUBROUTINE SUBROUTINE SET_DATA_PTR_2RD(YLFV, PTR) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV REAL(C_DOUBLE), POINTER, INTENT(IN) :: PTR(:,:) INTEGER(C_INT), PARAMETER :: RANK = 2 INTEGER(C_INT) :: EXTENTS(RANK) INTEGER(C_INTPTR_T) :: BASE, OFFSETS(RANK) TYPE(C_PTR) :: DATA DATA = C_LOC(PTR(1,1)) BASE = TRANSFER(DATA, BASE) EXTENTS = SHAPE(PTR) OFFSETS = 0 IF (SIZE(PTR, 1) > 1) OFFSETS(1) = TRANSFER(C_LOC(PTR(2,1)), BASE) - BASE IF (SIZE(PTR, 2) > 1) OFFSETS(2) = TRANSFER(C_LOC(PTR(1,2)), BASE) - BASE CALL SET_DATA_PTR_METADATA(YLFV, DATA, STORAGE_SIZE(PTR)/8, RANK, EXTENTS, OFFSETS) END SUBROUTINE SUBROUTINE SET_DATA_PTR_3RM(YLFV, PTR) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV REAL(C_FLOAT), POINTER, INTENT(IN) :: PTR(:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 3 INTEGER(C_INT) :: EXTENTS(RANK) INTEGER(C_INTPTR_T) :: BASE, OFFSETS(RANK) TYPE(C_PTR) :: DATA DATA = C_LOC(PTR(1,1,1)) BASE = TRANSFER(DATA, BASE) EXTENTS = SHAPE(PTR) OFFSETS = 0 IF (SIZE(PTR, 1) > 1) OFFSETS(1) = TRANSFER(C_LOC(PTR(2,1,1)), BASE) - BASE IF (SIZE(PTR, 2) > 1) OFFSETS(2) = TRANSFER(C_LOC(PTR(1,2,1)), BASE) - BASE IF (SIZE(PTR, 3) > 1) OFFSETS(3) = TRANSFER(C_LOC(PTR(1,1,2)), BASE) - BASE CALL SET_DATA_PTR_METADATA(YLFV, DATA, STORAGE_SIZE(PTR)/8, RANK, EXTENTS, OFFSETS) END SUBROUTINE SUBROUTINE SET_DATA_PTR_3RD(YLFV, PTR) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV REAL(C_DOUBLE), POINTER, INTENT(IN) :: PTR(:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 3 INTEGER(C_INT) :: EXTENTS(RANK) INTEGER(C_INTPTR_T) :: BASE, OFFSETS(RANK) TYPE(C_PTR) :: DATA DATA = C_LOC(PTR(1,1,1)) BASE = TRANSFER(DATA, BASE) EXTENTS = SHAPE(PTR) OFFSETS = 0 IF (SIZE(PTR, 1) > 1) OFFSETS(1) = TRANSFER(C_LOC(PTR(2,1,1)), BASE) - BASE IF (SIZE(PTR, 2) > 1) OFFSETS(2) = TRANSFER(C_LOC(PTR(1,2,1)), BASE) - BASE IF (SIZE(PTR, 3) > 1) OFFSETS(3) = TRANSFER(C_LOC(PTR(1,1,2)), BASE) - BASE CALL SET_DATA_PTR_METADATA(YLFV, DATA, STORAGE_SIZE(PTR)/8, RANK, EXTENTS, OFFSETS) END SUBROUTINE SUBROUTINE SET_DATA_PTR_4RM(YLFV, PTR) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV REAL(C_FLOAT), POINTER, INTENT(IN) :: PTR(:,:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 4 INTEGER(C_INT) :: EXTENTS(RANK) INTEGER(C_INTPTR_T) :: BASE, OFFSETS(RANK) TYPE(C_PTR) :: DATA DATA = C_LOC(PTR(1,1,1,1)) BASE = TRANSFER(DATA, BASE) EXTENTS = SHAPE(PTR) OFFSETS = 0 IF (SIZE(PTR, 1) > 1) OFFSETS(1) = TRANSFER(C_LOC(PTR(2,1,1,1)), BASE) - BASE IF (SIZE(PTR, 2) > 1) OFFSETS(2) = TRANSFER(C_LOC(PTR(1,2,1,1)), BASE) - BASE IF (SIZE(PTR, 3) > 1) OFFSETS(3) = TRANSFER(C_LOC(PTR(1,1,2,1)), BASE) - BASE IF (SIZE(PTR, 4) > 1) OFFSETS(4) = TRANSFER(C_LOC(PTR(1,1,1,2)), BASE) - BASE CALL SET_DATA_PTR_METADATA(YLFV, DATA, STORAGE_SIZE(PTR)/8, RANK, EXTENTS, OFFSETS) END SUBROUTINE SUBROUTINE SET_DATA_PTR_4RD(YLFV, PTR) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV REAL(C_DOUBLE), POINTER, INTENT(IN) :: PTR(:,:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 4 INTEGER(C_INT) :: EXTENTS(RANK) INTEGER(C_INTPTR_T) :: BASE, OFFSETS(RANK) TYPE(C_PTR) :: DATA DATA = C_LOC(PTR(1,1,1,1)) BASE = TRANSFER(DATA, BASE) EXTENTS = SHAPE(PTR) OFFSETS = 0 IF (SIZE(PTR, 1) > 1) OFFSETS(1) = TRANSFER(C_LOC(PTR(2,1,1,1)), BASE) - BASE IF (SIZE(PTR, 2) > 1) OFFSETS(2) = TRANSFER(C_LOC(PTR(1,2,1,1)), BASE) - BASE IF (SIZE(PTR, 3) > 1) OFFSETS(3) = TRANSFER(C_LOC(PTR(1,1,2,1)), BASE) - BASE IF (SIZE(PTR, 4) > 1) OFFSETS(4) = TRANSFER(C_LOC(PTR(1,1,1,2)), BASE) - BASE CALL SET_DATA_PTR_METADATA(YLFV, DATA, STORAGE_SIZE(PTR)/8, RANK, EXTENTS, OFFSETS) END SUBROUTINE PURE FUNCTION FIELD_VIEW_GET_EXTENT(YLFV, FORTRAN_DIM) RESULT(EXTENT) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER, INTENT(IN) :: FORTRAN_DIM INTEGER(C_INT) :: EXTENT EXTENT = YLFV%EXTENTS(YLFV%RANK-FORTRAN_DIM+1) END FUNCTION PURE FUNCTION FIELD_VIEW_GET_STRIDE(YLFV, FORTRAN_DIM) RESULT(STRIDE) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER, INTENT(IN) :: FORTRAN_DIM INTEGER(C_INT) :: STRIDE STRIDE = YLFV%STRIDES(YLFV%RANK-FORTRAN_DIM+1) END FUNCTION PURE FUNCTION FIELD_VIEW_GET_DIM_ROLE(YLFV, FORTRAN_DIM) RESULT(ROLE) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER, INTENT(IN) :: FORTRAN_DIM INTEGER(C_INT) :: ROLE INTEGER(C_INT) :: C_DIM INTEGER(C_INT), PARAMETER :: DIM_ROLE_MASK = INT(Z'F', C_INT) C_DIM = YLFV%RANK-FORTRAN_DIM+1 ROLE = IAND(ISHFT(YLFV%INDEXING, -DIM_ROLE_BITS * (C_DIM - 1)), DIM_ROLE_MASK) END FUNCTION PURE FUNCTION FIELD_VIEW_GET_EXTENT_BY_ROLE(YLFV, DIM_ROLE) RESULT(EXTENT) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER, INTENT(IN) :: DIM_ROLE INTEGER(C_INT) :: EXTENT INTEGER :: FORTRAN_DIM EXTENT = 0 DO FORTRAN_DIM = 1, YLFV%RANK IF (FIELD_VIEW_GET_DIM_ROLE(YLFV, FORTRAN_DIM) == DIM_ROLE) THEN EXTENT = FIELD_VIEW_GET_EXTENT(YLFV, FORTRAN_DIM) RETURN ENDIF ENDDO END FUNCTION SUBROUTINE FIELD_VIEW_SET_NAME(YLFV, NAME) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV CHARACTER(LEN=*), TARGET, INTENT(IN) :: NAME YLFV%NAME = C_LOC(NAME(1:1)) YLFV%NAME_SIZE = LEN_TRIM(NAME) END SUBROUTINE SUBROUTINE FIELD_VIEW_GET_NAME_PTR(YLFV, NAME) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV CHARACTER(LEN=:), POINTER, INTENT(INOUT) :: NAME CHARACTER(LEN=YLFV%NAME_SIZE), POINTER :: F_STR CALL C_F_POINTER(YLFV%NAME, F_STR) NAME => F_STR END SUBROUTINE SUBROUTINE ASSERT_EXPECTED_RANK_AND_KIND(LABEL, YLFV, EXPECTED_RANK, EXPECTED_KIND) IMPLICIT NONE CHARACTER(LEN=*), INTENT(IN) :: LABEL TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER(C_INT), INTENT(IN) :: EXPECTED_RANK INTEGER(C_INT), INTENT(IN) :: EXPECTED_KIND IF (YLFV%RANK /= EXPECTED_RANK) THEN BLOCK CHARACTER(LEN=:), POINTER :: NAME CALL FIELD_VIEW_GET_NAME_PTR(YLFV, NAME) CALL ABORT_TRANS(TRIM(LABEL)//" FAILURE: FIELD "//TRIM(NAME)//" RANK MUST BE "//& & TRIM(TO_STR(EXPECTED_RANK))//" BUT IS "//TRIM(TO_STR(YLFV%RANK))) END BLOCK ENDIF IF (YLFV%KIND /= EXPECTED_KIND) THEN BLOCK CHARACTER(LEN=:), POINTER :: NAME CALL FIELD_VIEW_GET_NAME_PTR(YLFV, NAME) CALL ABORT_TRANS(TRIM(LABEL)//" FAILURE: FIELD "//TRIM(NAME)//" KIND MUST BE "//& & TRIM(TO_STR(EXPECTED_KIND))//" BUT IS "//TRIM(TO_STR(YLFV%KIND))) END BLOCK ENDIF CONTAINS FUNCTION TO_STR(I) RESULT(STR) INTEGER, INTENT(IN) :: I CHARACTER(LEN=32) :: STR WRITE(STR, '(I0)') I END FUNCTION TO_STR END SUBROUTINE SUBROUTINE GET_DATA_PTR_1RM(YLFV, PTR) IMPLICIT NONE TYPE(FIELD_VIEW), INTENT(IN) :: YLFV REAL(C_FLOAT), POINTER :: PTR(:) INTEGER(C_INT), PARAMETER :: RANK = 1 CALL ASSERT_EXPECTED_RANK_AND_KIND("GET_DATA_PTR_1RM", YLFV, RANK, C_FLOAT) IF (FIELD_VIEW_GET_STRIDE(YLFV, 1) == 1) THEN CALL C_F_POINTER(YLFV%DATA, PTR, [FIELD_VIEW_GET_EXTENT(YLFV, 1)]) ELSE BLOCK REAL(C_FLOAT), POINTER :: BACKING(:,:) INTEGER(C_INT) :: EXTENTS(RANK+1) EXTENTS(1) = FIELD_VIEW_GET_STRIDE(YLFV, 1) EXTENTS(2) = FIELD_VIEW_GET_EXTENT(YLFV, 1) CALL C_F_POINTER(YLFV%DATA, BACKING, EXTENTS) PTR => BACKING(1, 1:FIELD_VIEW_GET_EXTENT(YLFV, 1)) END BLOCK ENDIF END SUBROUTINE SUBROUTINE GET_DATA_PTR_1RD(YLFV, PTR) IMPLICIT NONE TYPE(FIELD_VIEW), INTENT(IN) :: YLFV REAL(C_DOUBLE), POINTER, INTENT(INOUT) :: PTR(:) INTEGER(C_INT), PARAMETER :: RANK = 1 CALL ASSERT_EXPECTED_RANK_AND_KIND("GET_DATA_PTR_1RD", YLFV, RANK, C_DOUBLE) IF (FIELD_VIEW_GET_STRIDE(YLFV, 1) == 1) THEN CALL C_F_POINTER(YLFV%DATA, PTR, [FIELD_VIEW_GET_EXTENT(YLFV, 1)]) ELSE BLOCK REAL(C_DOUBLE), POINTER :: BACKING(:,:) INTEGER(C_INT) :: EXTENTS(RANK+1) EXTENTS(1) = FIELD_VIEW_GET_STRIDE(YLFV, 1) EXTENTS(2) = FIELD_VIEW_GET_EXTENT(YLFV, 1) CALL C_F_POINTER(YLFV%DATA, BACKING, EXTENTS) PTR => BACKING(1, 1:FIELD_VIEW_GET_EXTENT(YLFV, 1)) END BLOCK ENDIF END SUBROUTINE SUBROUTINE GET_DATA_PTR_2RM(YLFV, PTR) IMPLICIT NONE TYPE(FIELD_VIEW), INTENT(IN) :: YLFV REAL(C_FLOAT), POINTER, INTENT(INOUT) :: PTR(:,:) REAL(C_FLOAT), POINTER :: BACKING(:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 2 INTEGER(C_INT) :: EXTENTS(RANK+1), JDIM CALL ASSERT_EXPECTED_RANK_AND_KIND("GET_DATA_PTR_2RM", YLFV, RANK, C_FLOAT) EXTENTS(1) = FIELD_VIEW_GET_STRIDE(YLFV, 1) DO JDIM=1,RANK-1 EXTENTS(JDIM+1) = FIELD_VIEW_GET_STRIDE(YLFV, JDIM+1)/FIELD_VIEW_GET_STRIDE(YLFV, JDIM) ENDDO EXTENTS(RANK+1) = FIELD_VIEW_GET_EXTENT(YLFV, RANK) CALL C_F_POINTER(YLFV%DATA, BACKING, EXTENTS) PTR => BACKING(1, 1:FIELD_VIEW_GET_EXTENT(YLFV, 1), 1:FIELD_VIEW_GET_EXTENT(YLFV, 2)) END SUBROUTINE SUBROUTINE GET_DATA_PTR_2RD(YLFV, PTR) IMPLICIT NONE TYPE(FIELD_VIEW), INTENT(IN) :: YLFV REAL(C_DOUBLE), POINTER, INTENT(INOUT) :: PTR(:,:) REAL(C_DOUBLE), POINTER :: BACKING(:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 2 INTEGER(C_INT) :: EXTENTS(RANK+1), JDIM CALL ASSERT_EXPECTED_RANK_AND_KIND("GET_DATA_PTR_2RD", YLFV, RANK, C_DOUBLE) EXTENTS(1) = FIELD_VIEW_GET_STRIDE(YLFV, 1) DO JDIM=1,RANK-1 EXTENTS(JDIM+1) = FIELD_VIEW_GET_STRIDE(YLFV, JDIM+1)/FIELD_VIEW_GET_STRIDE(YLFV, JDIM) ENDDO EXTENTS(RANK+1) = FIELD_VIEW_GET_EXTENT(YLFV, RANK) CALL C_F_POINTER(YLFV%DATA, BACKING, EXTENTS) PTR => BACKING(1, 1:FIELD_VIEW_GET_EXTENT(YLFV, 1), 1:FIELD_VIEW_GET_EXTENT(YLFV, 2)) END SUBROUTINE SUBROUTINE GET_DATA_PTR_3RM(YLFV, PTR) IMPLICIT NONE TYPE(FIELD_VIEW), INTENT(IN) :: YLFV REAL(C_FLOAT), POINTER, INTENT(INOUT) :: PTR(:,:,:) REAL(C_FLOAT), POINTER :: BACKING(:,:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 3 INTEGER(C_INT) :: EXTENTS(RANK+1), JDIM CALL ASSERT_EXPECTED_RANK_AND_KIND("GET_DATA_PTR_3RM", YLFV, RANK, C_FLOAT) EXTENTS(1) = FIELD_VIEW_GET_STRIDE(YLFV, 1) DO JDIM=1,RANK-1 EXTENTS(JDIM+1) = FIELD_VIEW_GET_STRIDE(YLFV, JDIM+1)/FIELD_VIEW_GET_STRIDE(YLFV, JDIM) ENDDO EXTENTS(RANK+1) = FIELD_VIEW_GET_EXTENT(YLFV, RANK) CALL C_F_POINTER(YLFV%DATA, BACKING, EXTENTS) PTR => BACKING(1, 1:FIELD_VIEW_GET_EXTENT(YLFV, 1), 1:FIELD_VIEW_GET_EXTENT(YLFV, 2), & & 1:FIELD_VIEW_GET_EXTENT(YLFV, 3)) END SUBROUTINE SUBROUTINE GET_DATA_PTR_3RD(YLFV, PTR) IMPLICIT NONE TYPE(FIELD_VIEW), INTENT(IN) :: YLFV REAL(C_DOUBLE), POINTER, INTENT(INOUT) :: PTR(:,:,:) REAL(C_DOUBLE), POINTER :: BACKING(:,:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 3 INTEGER(C_INT) :: EXTENTS(RANK+1), JDIM CALL ASSERT_EXPECTED_RANK_AND_KIND("GET_DATA_PTR_3RD", YLFV, RANK, C_DOUBLE) EXTENTS(1) = FIELD_VIEW_GET_STRIDE(YLFV, 1) DO JDIM=1,RANK-1 EXTENTS(JDIM+1) = FIELD_VIEW_GET_STRIDE(YLFV, JDIM+1)/FIELD_VIEW_GET_STRIDE(YLFV, JDIM) ENDDO EXTENTS(RANK+1) = FIELD_VIEW_GET_EXTENT(YLFV, RANK) CALL C_F_POINTER(YLFV%DATA, BACKING, EXTENTS) PTR => BACKING(1, 1:FIELD_VIEW_GET_EXTENT(YLFV, 1), 1:FIELD_VIEW_GET_EXTENT(YLFV, 2), & & 1:FIELD_VIEW_GET_EXTENT(YLFV, 3)) END SUBROUTINE SUBROUTINE GET_DATA_PTR_4RM(YLFV, PTR) IMPLICIT NONE TYPE(FIELD_VIEW), INTENT(IN) :: YLFV REAL(C_FLOAT), POINTER, INTENT(INOUT) :: PTR(:,:,:,:) REAL(C_FLOAT), POINTER :: BACKING(:,:,:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 4 INTEGER(C_INT) :: EXTENTS(RANK+1), JDIM CALL ASSERT_EXPECTED_RANK_AND_KIND("GET_DATA_PTR_4RM", YLFV, RANK, C_FLOAT) EXTENTS(1) = FIELD_VIEW_GET_STRIDE(YLFV, 1) DO JDIM=1,RANK-1 EXTENTS(JDIM+1) = FIELD_VIEW_GET_STRIDE(YLFV, JDIM+1)/FIELD_VIEW_GET_STRIDE(YLFV, JDIM) ENDDO EXTENTS(RANK+1) = FIELD_VIEW_GET_EXTENT(YLFV, RANK) CALL C_F_POINTER(YLFV%DATA, BACKING, EXTENTS) PTR => BACKING(1, 1:FIELD_VIEW_GET_EXTENT(YLFV, 1), 1:FIELD_VIEW_GET_EXTENT(YLFV, 2), & & 1:FIELD_VIEW_GET_EXTENT(YLFV, 3), 1:FIELD_VIEW_GET_EXTENT(YLFV, 4)) END SUBROUTINE SUBROUTINE GET_DATA_PTR_4RD(YLFV, PTR) IMPLICIT NONE TYPE(FIELD_VIEW), INTENT(IN) :: YLFV REAL(C_DOUBLE), POINTER, INTENT(INOUT) :: PTR(:,:,:,:) REAL(C_DOUBLE), POINTER :: BACKING(:,:,:,:,:) INTEGER(C_INT), PARAMETER :: RANK = 4 INTEGER(C_INT) :: EXTENTS(RANK+1), JDIM CALL ASSERT_EXPECTED_RANK_AND_KIND("GET_DATA_PTR_4RD", YLFV, RANK, C_DOUBLE) EXTENTS(1) = FIELD_VIEW_GET_STRIDE(YLFV, 1) DO JDIM=1,RANK-1 EXTENTS(JDIM+1) = FIELD_VIEW_GET_STRIDE(YLFV, JDIM+1)/FIELD_VIEW_GET_STRIDE(YLFV, JDIM) ENDDO EXTENTS(RANK+1) = FIELD_VIEW_GET_EXTENT(YLFV, RANK) CALL C_F_POINTER(YLFV%DATA, BACKING, EXTENTS) PTR => BACKING(1, 1:FIELD_VIEW_GET_EXTENT(YLFV, 1), 1:FIELD_VIEW_GET_EXTENT(YLFV, 2), & & 1:FIELD_VIEW_GET_EXTENT(YLFV, 3), 1:FIELD_VIEW_GET_EXTENT(YLFV, 4)) END SUBROUTINE SUBROUTINE FIELD_VIEW_SET_IVSET_PTR(YLFV, IVSET, IVSET_BASE) TYPE(FIELD_VIEW), INTENT(INOUT) :: YLFV INTEGER(KIND=C_INT), TARGET, OPTIONAL, INTENT(IN) :: IVSET(:) INTEGER(KIND=C_INT), OPTIONAL, INTENT(IN) :: IVSET_BASE YLFV%IVSET_BASE = 1 IF (PRESENT(IVSET_BASE)) YLFV%IVSET_BASE = IVSET_BASE IF (PRESENT(IVSET)) THEN IF (SIZE(IVSET) > 0) THEN YLFV%IVSET = C_LOC(IVSET(1)) YLFV%IVSET_SIZE = SIZE(IVSET) RETURN ENDIF ENDIF YLFV%IVSET = C_NULL_PTR YLFV%IVSET_SIZE = 0 END SUBROUTINE SUBROUTINE FIELD_VIEW_GET_IVSET_PTR(YLFV, IVSET) TYPE(FIELD_VIEW), INTENT(IN) :: YLFV INTEGER(KIND=C_INT), POINTER, INTENT(INOUT) :: IVSET(:) IF (YLFV%IVSET_SIZE == 0) THEN NULLIFY(IVSET) ELSE CALL C_F_POINTER(YLFV%IVSET, IVSET, [YLFV%IVSET_SIZE]) ENDIF END SUBROUTINE END MODULE ECTRANS_FIELD_VIEW_MOD