!DEC$ FREEFORM
!-----------------------------------------------------------------------------------
!-----------------------------------------------------------------------------------
! UELlib:
! MODULE provides interface to Abaqus-implementation
! - especially the kinds of real and integer variables that Abaqus defines
!   implicitely in ABA_PARAM.INC. The corresponding variables AbqRK and AbqIK are
!   read from the implcitely defined variables i and r. Using AbqRK and AbqIK own
!   routines can use explcit type declaration
! - headers to the Abaqus utility routines
!
! Geralf Hütter, 2013/09/04
!
! distributed under CC BY-NC-SA 4.0 license
! (https://creativecommons.org/licenses/by-nc-sa/4.0/)
!
! Please refer to doc/UELlib.pdf for a description, references and further information.
!-----------------------------------------------------------------------------------
!-----------------------------------------------------------------------------------

MODULE ABQINTERFACE
   USE iso_c_binding
   INCLUDE 'ABA_PARAM.INC'
   PRIVATE
   INTEGER,PARAMETER,PUBLIC::AbqRK=KIND(r),AbqIK=KIND(i)
   PUBLIC::SPRINC,SINV,SPRIND,ROTSIG,SMAIntArrayCreate,SMAIntArrayAccess,&
           SMAIntArrayDelete,SMAFloatArrayCreateSP,SMAFloatArrayCreateDP,&
           SMAFloatArrayAccess,SMAFloatArrayDelete,SMAFloatArrayCreate,&
           AbaqusArrayCreate,AbaqusArrayAccess,AbaqusArrayDelete
   INTERFACE
     SUBROUTINE SPRINC(S,PS,LSTR,NDI,NSHR)
       INCLUDE 'ABA_PARAM.INC'
       DIMENSION::S(*),PS(*)
     END SUBROUTINE
     SUBROUTINE SINV(STRESS,SINV1,SINV2,NDI,NSHR)
       INCLUDE 'ABA_PARAM.INC'
       DIMENSION::STRESS(*)
     END SUBROUTINE
     SUBROUTINE SPRIND(S,PS,AN,LSTR,NDI,NSHR)
       INCLUDE 'ABA_PARAM.INC'
       DIMENSION::S(*),PS(3),AN(3,3)
     END SUBROUTINE
     SUBROUTINE ROTSIG(S,R,SPRIME,LSTR,NDI,NSHR)
       INCLUDE 'ABA_PARAM.INC'
       DIMENSION::S(*),R(*),SPRIME(*)
     END SUBROUTINE
     FUNCTION SMAIntArrayCreate(ID,SIZE,INITVAL)
       INTEGER(KIND=8) :: SMAIntArrayCreate
       INTEGER(KIND=4) :: ID,SIZE,INITVAL
     END FUNCTION SMAIntArrayCreate
     FUNCTION SMAIntArrayAccess(ID)
        INTEGER(KIND=8) :: SMAIntArrayAccess
        INTEGER(KIND=4) :: ID
     END FUNCTION SMAIntArrayAccess
     SUBROUTINE SMAIntArrayDelete(ID)
        INTEGER(KIND=4) :: ID
     END SUBROUTINE SMAIntArrayDelete  
     FUNCTION SMAFloatArrayCreateSP(ID,SIZE,INITVAL)
        INTEGER(KIND=8) :: SMAFloatArrayCreateSP
        INTEGER(KIND=4),INTENT(IN) :: ID
        INTEGER(KIND=4),INTENT(IN) :: SIZE
        REAL(KIND=4),   INTENT(IN) :: INITVAL
     END FUNCTION SMAFloatArrayCreateSP
     FUNCTION SMAFloatArrayCreateDP(ID,SIZE,INITVAL)
        INTEGER(KIND=8) :: SMAFloatArrayCreateDP
        INTEGER(KIND=4),INTENT(IN) :: ID
        INTEGER(KIND=4),INTENT(IN) :: SIZE
        REAL(KIND=8),   INTENT(IN) :: INITVAL
     END FUNCTION SMAFloatArrayCreateDP
     FUNCTION SMAFloatArrayAccess(ID)
        INTEGER(KIND=8) :: SMAFloatArrayAccess
        INTEGER(KIND=4) :: ID
     END FUNCTION SMAFloatArrayAccess
     SUBROUTINE SMAFloatArrayDelete(ID)
        INTEGER(KIND=4) :: ID 
     END SUBROUTINE SMAFloatArrayDelete 
    END INTERFACE
    INTERFACE SMAFloatArrayCreate
       PROCEDURE SMAFloatArrayCreateSP
       PROCEDURE SMAFloatArrayCreateDP
    END INTERFACE SMAFloatArrayCreate
    !interfaces to the subroutine versions which return FORTRAN Standard compliant Pointers
    INTERFACE AbaqusArrayCreate
      MODULE PROCEDURE SMAIntArrayCreateFortran1D
      MODULE PROCEDURE SMAIntArrayCreateFortran2D
      MODULE PROCEDURE SMAIntArrayCreateFortran1D_dp
      MODULE PROCEDURE SMAIntArrayCreateFortran2D_dp
      MODULE PROCEDURE SMAFloatArrayCreateFortran1D
      MODULE PROCEDURE SMAFloatArrayCreateFortran2D  
      MODULE PROCEDURE SMAFloatArrayCreateFortran3D  
      MODULE PROCEDURE SMAFloatArrayCreateFortran5D   
    END INTERFACE AbaqusArrayCreate
    INTERFACE AbaqusArrayAccess
      MODULE PROCEDURE SMAIntArrayAccessFortran1D
      MODULE PROCEDURE SMAIntArrayAccessFortran2D
      MODULE PROCEDURE SMAIntArrayAccessFortran1D_dp
      MODULE PROCEDURE SMAIntArrayAccessFortran2D_dp
      MODULE PROCEDURE SMAFloatArrayAccessFortran1D
      MODULE PROCEDURE SMAFloatArrayAccessFortran2D
      MODULE PROCEDURE SMAFloatArrayAccessFortran3D
      MODULE PROCEDURE SMAFloatArrayAccessFortran5D
    END INTERFACE AbaqusArrayAccess
    INTERFACE AbaqusArrayDelete
      MODULE PROCEDURE SMAIntArrayDeleteFortran1D
      MODULE PROCEDURE SMAIntArrayDeleteFortran2D
      MODULE PROCEDURE SMAIntArrayDeleteFortran1D_dp
      MODULE PROCEDURE SMAIntArrayDeleteFortran2D_dp
      MODULE PROCEDURE SMAFloatArrayDeleteFortran1D
      MODULE PROCEDURE SMAFloatArrayDeleteFortran2D
      MODULE PROCEDURE SMAFloatArrayDeleteFortran3D
      MODULE PROCEDURE SMAFloatArrayDeleteFortran5D
    END INTERFACE AbaqusArrayDelete
    
    CONTAINS

        SUBROUTINE SMAIntArrayCreateFortran1D(Array, ID, SIZE, INITVAL )
        
            INTEGER(KIND=4),POINTER:: Array(:)
            INTEGER,TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
            INTEGER(KIND=4),INTENT(IN) :: INITVAL
    
            pt_x=SMAIntArrayCreate( ID, SIZE(1), INITVAL )
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAIntArrayCreateFortran1D
        
        SUBROUTINE SMAIntArrayCreateFortran2D(Array, ID, SIZE, INITVAL )
        
            INTEGER(KIND=4),POINTER:: Array(:,:)
            INTEGER,TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
            INTEGER(KIND=4),INTENT(IN) :: INITVAL
    
            pt_x=SMAIntArrayCreate( ID, SIZE(1)*SIZE(2), INITVAL )
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAIntArrayCreateFortran2D
    
        
        SUBROUTINE SMAIntArrayCreateFortran1D_dp(Array, ID, SIZE, INITVAL )
            
            INTEGER(KIND=8),POINTER:: Array(:)
            INTEGER,TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
            INTEGER(KIND=8),INTENT(IN) :: INITVAL
    
            pt_x=SMAFloatArrayCreateDP( ID, SIZE(1), REAL(INITVAL,8) )
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAIntArrayCreateFortran1D_dp
        
        SUBROUTINE SMAIntArrayCreateFortran2D_dp(Array, ID, SIZE, INITVAL )
    
            INTEGER(KIND=8),POINTER:: Array(:,:)
            INTEGER,TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
            INTEGER(KIND=8),INTENT(IN) :: INITVAL
    
            pt_x=SMAFloatArrayCreateDP( ID, SIZE(1)*SIZE(2), REAL(INITVAL,8) )
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAIntArrayCreateFortran2D_dp
    
        SUBROUTINE SMAIntArrayAccessFortran1D(Array, ID, SIZE )
    
            INTEGER(KIND=4),POINTER:: Array(:)
            INTEGER,TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
            
            pt_x=SMAIntArrayAccess(ID)
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAIntArrayAccessFortran1D
        
        SUBROUTINE SMAIntArrayAccessFortran2D(Array, ID, SIZE )
    
            INTEGER(KIND=4),POINTER:: Array(:,:)
            INTEGER,TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
    
            pt_x=SMAIntArrayAccess(ID)
            CALL C_F_POINTER(C_LOC(x), Array, SIZE)
            
        END SUBROUTINE SMAIntArrayAccessFortran2D
    
        SUBROUTINE SMAIntArrayAccessFortran1D_dp(Array, ID, SIZE )
    
            INTEGER(KIND=8),POINTER:: Array(:)
            INTEGER,TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
            
            pt_x=SMAFloatArrayAccess(ID)
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAIntArrayAccessFortran1D_dp
        
        SUBROUTINE SMAIntArrayAccessFortran2D_dp(Array, ID, SIZE )
    
            INTEGER(KIND=8),POINTER:: Array(:,:)
            INTEGER,TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
            
            pt_x=SMAFloatArrayAccess(ID)
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAIntArrayAccessFortran2D_dp
    
        SUBROUTINE SMAIntArrayDeleteFortran1D(Array,ID)
                
                INTEGER(KIND=4),INTENT(IN) :: ID
                INTEGER,POINTER:: Array(:)
                
                CALL SMAIntArrayDelete(ID)
                
        END SUBROUTINE SMAIntArrayDeleteFortran1D
        
        SUBROUTINE SMAIntArrayDeleteFortran2D(Array,ID)
                
                INTEGER(KIND=4),INTENT(IN) :: ID
                INTEGER,POINTER:: Array(:,:)
                
                CALL SMAIntArrayDelete(ID)
                
        END SUBROUTINE SMAIntArrayDeleteFortran2D
        
        SUBROUTINE SMAIntArrayDeleteFortran1D_dp(Array,ID)
        
                INTEGER(KIND=8),POINTER:: Array(:)
                INTEGER(KIND=4),INTENT(IN) :: ID
                
                CALL SMAFloatArrayDelete(ID)
                
        END SUBROUTINE SMAIntArrayDeleteFortran1D_dp
        
        SUBROUTINE SMAIntArrayDeleteFortran2D_dp(Array,ID)
        
                INTEGER(KIND=8),POINTER:: Array(:,:)
                INTEGER(KIND=4),INTENT(IN) :: ID
                
                CALL SMAFloatArrayDelete(ID)
                
        END SUBROUTINE SMAIntArrayDeleteFortran2D_dp
    
    
        SUBROUTINE SMAFloatArrayCreateFortran1D(Array, ID, SIZE, INITVAL )
    
            REAL(KIND=AbqRK),POINTER:: Array(:)
            REAL(KIND=AbqRK),TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
            REAL(KIND=AbqRK),INTENT(IN) :: INITVAL
    
            pt_x=SMAFloatArrayCreate( ID, SIZE(1), INITVAL )
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAFloatArrayCreateFortran1D
        
        SUBROUTINE SMAFloatArrayCreateFortran2D(Array, ID, SIZE, INITVAL )
    
            REAL(KIND=AbqRK),POINTER:: Array(:,:)
            REAL(KIND=AbqRK),TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),INTENT(IN),DIMENSION(:) :: SIZE
            REAL(KIND=AbqRK),INTENT(IN) :: INITVAL
    
            pt_x=SMAFloatArrayCreate( ID, SIZE(1)*SIZE(2), INITVAL )
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAFloatArrayCreateFortran2D
        
        SUBROUTINE SMAFloatArrayCreateFortran3D(Array, ID, SIZE, INITVAL )
    
            REAL(KIND=AbqRK),POINTER:: Array(:,:,:)
            REAL(KIND=AbqRK),TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),INTENT(IN),DIMENSION(:) :: SIZE
            REAL(KIND=AbqRK),INTENT(IN) :: INITVAL
    
            pt_x=SMAFloatArrayCreate( ID, SIZE(1)*SIZE(2)*SIZE(3), INITVAL )
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAFloatArrayCreateFortran3D
        
        SUBROUTINE SMAFloatArrayCreateFortran5D(Array, ID, SIZE, INITVAL )
    
            REAL(KIND=AbqRK),POINTER:: Array(:,:,:,:,:)
            REAL(KIND=AbqRK),TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),INTENT(IN),DIMENSION(:) :: SIZE
            REAL(KIND=AbqRK),INTENT(IN) :: INITVAL
    
            pt_x=SMAFloatArrayCreate(ID,SIZE(1)*SIZE(2)*SIZE(3)*SIZE(4)*SIZE(5)&
                                                                       ,INITVAL)
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAFloatArrayCreateFortran5D
    
        SUBROUTINE SMAFloatArrayAccessFortran1D(Array, ID, SIZE )
    
            REAL(KIND=AbqRK),POINTER:: Array(:)
            REAL(KIND=AbqRK),TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),DIMENSION(:),INTENT(IN) :: SIZE
    
            pt_x=SMAFloatArrayAccess(ID)
            CALL C_F_POINTER(C_LOC(x), Array,SIZE)
            
        END SUBROUTINE SMAFloatArrayAccessFortran1D
    
    
        SUBROUTINE SMAFloatArrayAccessFortran2D(Array, ID, SIZE )
    
            REAL(KIND=AbqRK),POINTER:: Array(:,:)
            REAL(KIND=AbqRK),TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),INTENT(IN),DIMENSION(:) :: SIZE
    
            pt_x=SMAFloatArrayAccess(ID)
            CALL C_F_POINTER(C_LOC(x), Array, SIZE)
            
        END SUBROUTINE SMAFloatArrayAccessFortran2D
        
        SUBROUTINE SMAFloatArrayAccessFortran3D(Array, ID, SIZE )
    
            REAL(KIND=AbqRK),POINTER:: Array(:,:,:)
            REAL(KIND=AbqRK),TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),INTENT(IN),DIMENSION(:) :: SIZE
    
            pt_x=SMAFloatArrayAccess(ID)
            CALL C_F_POINTER(C_LOC(x), Array, SIZE)
            
        END SUBROUTINE SMAFloatArrayAccessFortran3D
        
        SUBROUTINE SMAFloatArrayAccessFortran5D(Array, ID, SIZE )
    
            REAL(KIND=AbqRK),POINTER:: Array(:,:,:,:,:)
            REAL(KIND=AbqRK),TARGET:: x
            POINTER(pt_x,x)
            INTEGER(KIND=4),INTENT(IN) :: ID
            INTEGER(KIND=4),INTENT(IN),DIMENSION(:) :: SIZE
    
            pt_x=SMAFloatArrayAccess(ID)
            CALL C_F_POINTER(C_LOC(x), Array, SIZE)
            
        END SUBROUTINE SMAFloatArrayAccessFortran5D
        
        SUBROUTINE SMAFloatArrayDeleteFortran1D(Array, ID )
        
                INTEGER(KIND=4) :: ID
                REAL(KIND=AbqRK),POINTER:: Array(:)
                CALL SMAFloatArrayDelete( ID )
                
        END SUBROUTINE SMAFloatArrayDeleteFortran1D
        
        SUBROUTINE SMAFloatArrayDeleteFortran2D(Array, ID )
        
                INTEGER(KIND=4) :: ID
                REAL(KIND=AbqRK),POINTER:: Array(:,:)
                CALL SMAFloatArrayDelete( ID )
                
        END SUBROUTINE SMAFloatArrayDeleteFortran2D
        
        SUBROUTINE SMAFloatArrayDeleteFortran3D(Array, ID )
        
                INTEGER(KIND=4) :: ID
                REAL(KIND=AbqRK),POINTER:: Array(:,:,:)
                CALL SMAFloatArrayDelete( ID )
                
        END SUBROUTINE SMAFloatArrayDeleteFortran3D
        
        SUBROUTINE SMAFloatArrayDeleteFortran5D(Array, ID )
        
                INTEGER(KIND=4) :: ID
                REAL(KIND=AbqRK),POINTER:: Array(:,:,:,:,:)
                CALL SMAFloatArrayDelete( ID )
                
        END SUBROUTINE SMAFloatArrayDeleteFortran5D

END MODULE
