!DEC$ FREEFORM
!=============================================================================
! Monolithic FE^2
! Nils Lange, Geralf Huetter, Bjoern Kiefer
!   Nils.Lange@imfd.tu-freiberg.de, Geralf.Huetter@imfd.tu-freiberg.de, 
!   Bjoern.Kiefer@imfd.tu-freiberg.de
! distributed under CC BY-NC-SA 4.0 license
! (https://creativecommons.org/licenses/by-nc-sa/4.0/)
! Reference: 
!   N. Lange, G. Huetter, B. Kiefer: "An efficient monolithic solution scheme for FE2 problems",
!   https://arxiv.org/abs/2101.01802
!
! Further information on the implementation, structure of the source code,
! examples and tutorials can be found in the file doc/documentation.pdf
! 
!=============================================================================

MODULE type_meshparameters
    !this modul declares an object named meshparameters, which bundels all
    !information that defines the microscopic mesh; it has the methods
    !read_data, get_pointer and deallocate_data

    USE ABQINTERFACE
    USE ABQSMA
    USE type_analysisparameters
    
    PRIVATE::To_upper
    PUBLIC

    TYPE meshparameters
    
        !-----------------------mesh parameters--------------------------------
        INTEGER,POINTER:: dimens,nnodes_e,ndof_e,n_STATEV_elem,nElem,nNodes,&
                          nNonZero_reduced,nRows_reduced, nslaves,ndof_n,JTYPE,&
                          ndof_macro,nEquations,nreduced_master_slave
        !'equation's for enforcing the constraints
        REAL(KIND=AbqRK),DIMENSION(:,:),POINTER:: Equations
        INTEGER(KIND=4):: ID_Equations=1
        !connection master reduced dof <-> global master node label
        INTEGER,DIMENSION(:),POINTER:: master_reduced_to_global
        INTEGER(KIND=4):: ID_master_reduced_to_global=2
        !connection master reduced dof <-> global slave node label
        INTEGER,DIMENSION(:,:),POINTER::global_master_reduced_to_slave
        INTEGER(KIND=4):: ID_global_master_reduced_to_slave=3
        !CSR definition array for reduced stiffnessmatrix
        INTEGER,DIMENSION(:),POINTER:: rowIndex_reduced
        INTEGER(KIND=4):: ID_rowIndex_reduced=4
        !CSR definition array for reduced stiffnessmatrix
        INTEGER,DIMENSION(:),POINTER:: columnIndex_reduced
        INTEGER(KIND=4):: ID_columnIndex_reduced=5
        !coordinates of the Mesh
        REAL(KIND=AbqRK),DIMENSION(:),POINTER:: COORDSGLOBAL
        INTEGER(KIND=4):: ID_COORDSGLOBAL=6
        !element connection :element dof <-> global dof label
        INTEGER,DIMENSION(:,:),POINTER:: element_to_global_dof
        INTEGER(KIND=4):: ID_element_to_global_dof=7
        !element connection :element dof <-> reduced system dof
        INTEGER,DIMENSION(:,:),POINTER:: element_to_reduced_dof
        INTEGER(KIND=4):: ID_element_to_reduced_dof=8
        !element stiffnessmatrix to k_matrix_values
        INTEGER,DIMENSION(:,:),POINTER:: values_to_global_reduced
        INTEGER(KIND=4):: ID_values_to_global_reduced=9
        !conntection element <-> material label
        INTEGER,DIMENSION(:),POINTER:: element_to_material
        INTEGER(KIND=4):: ID_element_to_material=10
        !connection: node label <-> slave label
        INTEGER,DIMENSION(:),POINTER:: global_node_to_slave_node
        INTEGER(KIND=4):: ID_global_node_to_slave_node=11
        !width,height,depth(3D) of the RVE
        REAL(KIND=AbqRK),DIMENSION(:),POINTER:: delta_x
        INTEGER(KIND=4):: ID_delta_x=12
        !permutation matrix
        INTEGER,DIMENSION(:),POINTER:: perm
        INTEGER(KIND=4):: ID_perm=13
        !ID of scalar array (array containing scalars)
        INTEGER(KIND=4):: ID_scalars=14
        !total number of arrays +1
        INTEGER(KIND=4):: ID_total=15
        
        CONTAINS
        
            PROCEDURE:: read_data => read_data_procedure
            PROCEDURE:: get_pointer => get_pointer_procedure
            PROCEDURE:: deallocate_data => deallocate_data_procedure

    END TYPE meshparameters
    
    PRIVATE:: read_data_procedure,get_pointer_procedure,deallocate_data_procedure
    
CONTAINS

SUBROUTINE read_data_procedure(para,analysis,rve_number)

    IMPLICIT NONE

    CLASS(meshparameters)::para
    TYPE(analysisparameters)::analysis
    !dummy arrays
    INTEGER, DIMENSION(:),POINTER:: array_int
    REAL(KIND=AbqRK), DIMENSION(:),POINTER:: array_real
    INTEGER:: io_error , read_error,error
    !Name of directory in which Abaqus is stared
    CHARACTER*256  OUTDIR
    !lenght of name of this directory
    INTEGER:: LENOUTDIR
    !name of the current abaqus JOB
    CHARACTER*256 JOBNAME
    !lenght of thatname
    INTEGER:: LENJOBNAME
    !Label of the RVE
    INTEGER,INTENT(IN):: rve_number
    CHARACTER(LEN=1):: rve_number_str
    !integer with information-> RVE definition existing
    INTEGER:: active_RVE_definitions
    !RVE information
    CHARACTER(100):: description
    INTEGER:: k,i
    CHARACTER(len=500),DIMENSION(2):: line
    CHARACTER(len=100),DIMENSION(22):: Keywords
    CHARACTER(len=500),DIMENSION(16),PARAMETER:: NecessaryKeywords=['*PART','*DIMENSION','*ELEMENTNODES','*NODEDOF','*NDOF_MACRO',&
                                                                   '*SLAVENODES','*ELEMENTTYPE','*NODE','*ELEMENT_TO_GLOBAL_DOF',&
                                                                   '*ELEMENT_TO_REDUCED_DOF','*EQUATIONS','*ELEMENT_TO_MATERIAL',&
                                                                   '*RVE_DIMENSIONS','*MASTER_REDUCED_TO_GLOBAL','*GLOBAL_MASTER_REDUCED_TO_SLAVE',&
                                                                   '*GLOBAL_NODE_TO_SLAVE_NODE']
    CHARACTER(len=500),DIMENSION(3),PARAMETER:: NecessaryKeywords_SYMM=['*COLUMNINDEX_REDUCED','*ROWINDEX_REDUCED','*VALUES_TO_GLOBAL_REDUCED']
    CHARACTER(len=500),DIMENSION(3),PARAMETER:: NecessaryKeywords_UNSYMM=['*COLUMNINDEX_REDUCED_UNSYMM','*ROWINDEX_REDUCED_UNSYMM',&
                                                                          '*VALUES_TO_GLOBAL_REDUCED_UNSYMM']
                                                                          
    !get string of RVE number through internal read
    WRITE(rve_number_str,'(I1)') rve_number
    
    !------------------read meshinformation-------------------------------------
    CALL GETOUTDIR( OUTDIR, LENOUTDIR )!get directory name and length
    CALL GETJOBNAME( JOBNAME, LENJOBNAME ) !get job name and and length
    
        !----------------read data from file micromesh.FE---------------------
        
        !open file with mesh information
        OPEN(unit=25,file=OUTDIR(1:LENOUTDIR)//'/'//JOBNAME(1:LENJOBNAME)//'.FE'//&
        rve_number_str,status='old',action='read',iostat = io_error)
                     
        IF (io_error==0) THEN
        
            !integer mesh parameters
            CALL SMAIntArrayCreateFortran(array_int,-para%ID_total*rve_number+para%ID_scalars,14,0)
            !set the pointers to the integer array
            para%dimens                 => array_int(1)
            para%nnodes_e               => array_int(2)
            para%ndof_e                 => array_int(3)
            para%ndof_n                 => array_int(4)
            para%ndof_macro             => array_int(5)
            para%nslaves                => array_int(6)
            para%nElem                  => array_int(7)
            para%nNodes                 => array_int(8)
            para%JTYPE                  => array_int(9)
            para%nRows_reduced          => array_int(10)
            para%nNonZero_reduced       => array_int(11)
            para%nEquations             => array_int(12)
            para%nreduced_master_slave  => array_int(13)
            para%n_STATEV_elem          => array_int(14)

            read_error=0 !reports whether there was any error during the READ process
            
            k=1 !running index
            
            DO WHILE (.true.) !do until the end of file is reached
            
                READ(25,*,iostat=error) line

                IF (error/=0) THEN
                
                    EXIT
                
                ELSE
                
                    CALL To_upper(line(1)) !convert to upper cases
                    
                    IF (line(1)(1:1)=='*' .AND. line(1)(2:2)/='*') THEN !Keyword detected
                    
                        Keywords(k)=trim(line(1))
                        
                        SELECT CASE(Keywords(k)) !select the current statement
                        CASE('*PART') !output information about the RVE
                            CALL STDB_ABQERR(1_AbqIK,  'RVE-Nr. %I : '//line(2),[rve_number], 0.0_AbqRK, ' ')
                        CASE('*DIMENSION')
                            READ(line(2)(3:),*) para%dimens
                        CASE('*ELEMENTNODES')
                            READ(line(2)(3:),*) para%nnodes_e
                        CASE('*NODEDOF')
                            READ(line(2)(3:),*) para%ndof_n
                        CASE('*NDOF_MACRO') 
                            READ(line(2)(3:),*) para%ndof_macro
                        CASE('*SLAVENODES') 
                            READ(line(2)(3:),*) para%nslaves
                        CASE('*ELEMENTTYPE') 
                            READ(line(2),*) para%JTYPE
                        CASE('*NODE')
                            READ(line(2)(3:),*) para%nNodes
                            CALL SMAFloatArrayCreateFortran(para%COORDSGLOBAL,-para%ID_total*rve_number+para%ID_COORDSGLOBAL,para%nNodes*para%ndof_n,0.0_AbqRK)
                            DO i=1,para%nNodes
                                IF (error==0) READ(25,*,iostat=error) para%COORDSGLOBAL((i-1)*para%dimens+1:i*para%dimens)
                            END DO
                        CASE('*ELEMENT_TO_GLOBAL_DOF')
                            READ(line(2)(3:),*) para%nElem
                            para%ndof_e=para%nnodes_e*para%ndof_n
                            CALL SMAIntArrayCreateFortran(array_int,-para%ID_total*rve_number+para%ID_element_to_global_dof,para%nElem*para%ndof_e,0)
                            DO i=1,para%nElem
                                IF (error==0) READ(25,*,iostat=error) array_int((i-1)*para%ndof_e+1:i*para%ndof_e)
                            END DO
                            CALL SMAIntArrayAccessFortran2D(para%element_to_global_dof,-para%ID_total*rve_number+para%ID_element_to_global_dof,[para%ndof_e,para%nElem])
                        CASE('*ELEMENT_TO_REDUCED_DOF')
                            READ(line(2)(3:),*) para%nElem
                            para%ndof_e=para%nnodes_e*para%ndof_n
                            CALL SMAIntArrayCreateFortran(array_int,-para%ID_total*rve_number+para%ID_element_to_reduced_dof,para%nElem*para%ndof_e,0)
                            DO i=1,para%nElem
                                IF (error==0) READ(25,*,iostat=error) array_int((i-1)*para%ndof_e+1:i*para%ndof_e)
                            END DO
                            CALL SMAIntArrayAccessFortran2D(para%element_to_reduced_dof,-para%ID_total*rve_number+para%ID_element_to_reduced_dof,[para%ndof_e,para%nElem])
                        CASE('*EQUATIONS')
                            READ(line(2)(3:),*) para%nEquations
                            CALL SMAFloatArrayCreateFortran(array_real,-para%ID_total*rve_number+para%ID_Equations,(2+para%ndof_macro)*para%nEquations,0.0_AbqRK)
                            DO i=1,para%nEquations
                                IF (error==0) READ(25,*,iostat=error) array_real((i-1)*(2+para%ndof_macro)+1:i*(2+para%ndof_macro))
                            END DO
                            CALL SMAFloatArrayAccessFortran2D(para%Equations,-para%ID_total*rve_number+para%ID_Equations,[(2+para%ndof_macro),para%nEquations])
                        CASE('*ELEMENT_TO_MATERIAL')
                            READ(line(2)(3:),*) para%nElem
                            CALL SMAIntArrayCreateFortran(para%element_to_material,-para%ID_total*rve_number+para%ID_element_to_material,para%nElem,0)
                            READ (25,*,iostat=error) para%element_to_material
                        CASE('*RVE_DIMENSIONS')
                            READ(line(2)(3:),*) para%dimens
                            CALL SMAFloatArrayCreateFortran(para%delta_x,-para%ID_total*rve_number+para%ID_delta_x,para%dimens,0.0_AbqRK)
                            READ(25,*,iostat=read_error) para%delta_x
                        CASE('*COLUMNINDEX_REDUCED')
                            IF (analysis%symmetric_matrix) THEN
                                READ(line(2)(3:),*) para%nNonZero_reduced
                                CALL SMAIntArrayCreateFortran(para%columnIndex_reduced,-para%ID_total*rve_number+para%ID_columnIndex_reduced,para%nNonZero_reduced,0)
                                READ(25,*,iostat=error) para%columnIndex_reduced
                            ELSE
                                READ(25,*) !skip this line
                            END IF
                        CASE('*COLUMNINDEX_REDUCED_UNSYMM')
                            IF (.NOT. analysis%symmetric_matrix) THEN
                                READ(line(2)(3:),*) para%nNonZero_reduced
                                CALL SMAIntArrayCreateFortran(para%columnIndex_reduced,-para%ID_total*rve_number+para%ID_columnIndex_reduced,para%nNonZero_reduced,0)
                                READ(25,*,iostat=error) para%columnIndex_reduced
                            ELSE
                                READ(25,*) !skip this line
                            END IF
                        CASE('*ROWINDEX_REDUCED')
                            IF (analysis%symmetric_matrix) THEN
                                READ(line(2)(3:),*) para%nRows_reduced
                                para%nRows_reduced=para%nRows_reduced-1
                                CALL SMAIntArrayCreateFortran(para%rowIndex_reduced,-para%ID_total*rve_number+para%ID_rowIndex_reduced,para%nRows_reduced+1,0)
                                READ(25,*,iostat=error) para%rowIndex_reduced
                            ELSE
                                READ(25,*) !skip this line
                            END IF
                        CASE('*ROWINDEX_REDUCED_UNSYMM')
                            IF (.NOT. analysis%symmetric_matrix) THEN
                                READ(line(2)(3:),*) para%nRows_reduced
                                para%nRows_reduced=para%nRows_reduced-1
                                CALL SMAIntArrayCreateFortran(para%rowIndex_reduced,-para%ID_total*rve_number+para%ID_rowIndex_reduced,para%nRows_reduced+1,0)
                                READ(25,*,iostat=error) para%rowIndex_reduced
                            ELSE
                                READ(25,*) !skip this line
                            END IF
                        CASE('*VALUES_TO_GLOBAL_REDUCED')
                            READ(line(2)(3:),*) para%nElem
                            IF (analysis%symmetric_matrix) THEN
                                CALL SMAIntArrayCreateFortran(array_int,-para%ID_total*rve_number+para%ID_values_to_global_reduced,para%nElem*para%ndof_e**2,0)
                                DO i=1,para%nElem
                                    IF (error==0) READ(25,*,iostat=error) array_int((i-1)*para%ndof_e**2+1:i*para%ndof_e**2)
                                END DO
                                CALL SMAIntArrayAccessFortran2D(para%values_to_global_reduced,-para%ID_total*rve_number+para%ID_values_to_global_reduced,[para%ndof_e**2,para%nElem])
                            ELSE
                                DO i=1,para%nElem
                                    READ(25,*) !skip this line
                                END DO
                            END IF
                        CASE('*VALUES_TO_GLOBAL_REDUCED_UNSYMM')
                            READ(line(2)(3:),*) para%nElem
                            IF (.NOT. analysis%symmetric_matrix) THEN
                                CALL SMAIntArrayCreateFortran(array_int,-para%ID_total*rve_number+para%ID_values_to_global_reduced,para%nElem*para%ndof_e**2,0)
                                DO i=1,para%nElem
                                    IF (error==0) READ(25,*,iostat=error) array_int((i-1)*para%ndof_e**2+1:i*para%ndof_e**2)
                                END DO
                                CALL SMAIntArrayAccessFortran2D(para%values_to_global_reduced,-para%ID_total*rve_number+para%ID_values_to_global_reduced,[para%ndof_e**2,para%nElem])
                            ELSE
                                DO i=1,para%nElem
                                    READ(25,*) !skip this line
                                END DO
                            END IF
                        CASE('*MASTER_REDUCED_TO_GLOBAL')
                            READ(line(2)(3:),*) para%nRows_reduced
                            CALL SMAIntArrayCreateFortran(para%master_reduced_to_global,-para%ID_total*rve_number+para%ID_master_reduced_to_global,para%nRows_reduced,0)
                            READ(25,*,iostat=error) para%master_reduced_to_global
                        CASE('*GLOBAL_MASTER_REDUCED_TO_SLAVE')
                            READ(line(2)(3:),*) para%nreduced_master_slave
                            CALL SMAIntArrayCreateFortran(array_int,-para%ID_total*rve_number+para%ID_global_master_reduced_to_slave,para%nreduced_master_slave*2,0)
                            DO i=1,para%nreduced_master_slave
                                IF (error==0) READ(25,*,iostat=error) array_int((i-1)*2+1:i*2)
                            END DO
                            CALL SMAIntArrayAccessFortran2D(para%global_master_reduced_to_slave,-para%ID_total*rve_number+para%ID_global_master_reduced_to_slave,[2,para%nreduced_master_slave])
                        CASE('*GLOBAL_NODE_TO_SLAVE_NODE')
                            CALL SMAIntArrayCreateFortran(para%global_node_to_slave_node,-para%ID_total*rve_number+para%ID_global_node_to_slave_node,para%nNodes*para%ndof_n,0)
                            READ(25,*,iostat=error) para%global_node_to_slave_node
                        CASE DEFAULT
                            CALL STDB_ABQERR(-3_AbqIK,  'An unrecognized keyword in the '//JOBNAME(1:LENJOBNAME)//'.FE'//&
                                   rve_number_str//' inputfile has been found.', 0_AbqIK , 0.0_AbqRK, ' ')
                        END SELECT
                        
                        k=k+1
                        
                    END IF
                END IF
            END DO
            
            CLOSE (unit=25) !close file
            
            !check the inputfile
            !check IF there has been an error in reading the file
            DO i=1,SIZE(NecessaryKeywords)
                IF (NOT(ANY(Keywords==NecessaryKeywords(i)))) read_error=1
            END DO
            IF (analysis%symmetric_matrix==1) THEN
                DO i=1,SIZE(NecessaryKeywords_SYMM)
                    IF (NOT(ANY(Keywords==NecessaryKeywords_SYMM(i)))) read_error=1
                END DO
            ELSE
                DO i=1,SIZE(NecessaryKeywords_UNSYMM)
                    IF (NOT(ANY(Keywords==NecessaryKeywords_UNSYMM(i)))) read_error=1
                END DO
            END IF
            !display an error and stop the simulation IF an error has been reported
            IF (read_error==1) CALL STDB_ABQERR(-3_AbqIK,  'An error in the '//JOBNAME(1:LENJOBNAME)//'.FE'//&
                                   TRIM(rve_number_str)//' inputfile has been found.', 0_AbqIK , 0.0_AbqRK, ' ')
            
            !permutationmatrix for reducing the bandwitdh
            CALL STDB_ABQERR(1_AbqIK,  'The solver reports for RVE-Nr. %I : ',[rve_number], 0.0_AbqRK, ' ')
            CALL SMAIntArrayCreateFortran(para%perm,-para%ID_total*rve_number+para%ID_perm,para%nRows_reduced,0)
                        
            !mark the RVE definition as active
            analysis%active_RVE_definitions(rve_number)=1
            
        ELSE
        
            CALL STDB_ABQERR(1_AbqIK,  'RVE-Nr. %I : no information supplied',[rve_number], 0.0_AbqRK, ' ')
                
        END IF
    
    
END SUBROUTINE read_data_procedure


SUBROUTINE get_pointer_procedure(para,rve_number)
    !get pointer to the mesh definition arrays

    IMPLICIT NONE

    CLASS(meshparameters)::para
    TYPE(analysisparameters)::analysis
    INTEGER:: rve_number
    INTEGER, DIMENSION(:),POINTER:: array_int
    
    CALL analysis%get_pointer()
    
    !-check if the RVE meshdata has been read before, if not stop the analysis-
    IF (analysis%active_RVE_definitions(rve_number)==0) THEN
        CALL STDB_ABQERR(-3_AbqIK, 'RVE Definition Nr. accessed by the UMAT'//&
             ' has no information!!',0, 0.0_AbqRK, ' ')
    END IF    

    CALL SMAIntArrayAccessFortran1D(array_int,-para%ID_total*rve_number+para%ID_scalars,11)
    
    para%dimens                 => array_int(1)
    para%nnodes_e               => array_int(2)
    para%ndof_e                 => array_int(3)
    para%ndof_n                 => array_int(4)
    para%ndof_macro             => array_int(5)
    para%nslaves                => array_int(6)
    para%nElem                  => array_int(7)
    para%nNodes                 => array_int(8)
    para%JTYPE                  => array_int(9)
    para%nRows_reduced          => array_int(10)
    para%nNonZero_reduced       => array_int(11)
    para%nEquations             => array_int(12)
    para%nreduced_master_slave  => array_int(13)
    para%n_STATEV_elem          => array_int(14)

    
    CALL SMAFloatArrayAccessFortran1D(para%delta_x,-para%ID_total*rve_number+para%ID_delta_x,para%dimens)
    
    CALL SMAFloatArrayAccessFortran1D(para%COORDSGLOBAL,-para%ID_total*rve_number+para%ID_COORDSGLOBAL,para%nNodes*para%dimens)
    
    CALL SMAIntArrayAccessFortran1D(para%master_reduced_to_global,-para%ID_total*rve_number+para%ID_master_reduced_to_global,para%nRows_reduced)
    
    CALL SMAIntArrayAccessFortran2D(para%element_to_global_dof,-para%ID_total*rve_number+para%ID_element_to_global_dof,[para%ndof_e,para%nElem])
    
    CALL SMAIntArrayAccessFortran2D(para%element_to_reduced_dof,-para%ID_total*rve_number+para%ID_element_to_reduced_dof,[para%ndof_e,para%nElem])
    
    CALL SMAIntArrayAccessFortran1D(para%rowIndex_reduced,-para%ID_total*rve_number+para%ID_rowIndex_reduced,para%nRows_reduced+1)
    
    CALL SMAIntArrayAccessFortran1D(para%columnIndex_reduced,-para%ID_total*rve_number+para%ID_columnIndex_reduced,para%nNonZero_reduced)
    
    CALL SMAIntArrayAccessFortran2D(para%values_to_global_reduced,-para%ID_total*rve_number+para%ID_values_to_global_reduced,[para%ndof_e**2,para%nElem])
    
    CALL SMAIntArrayAccessFortran2D(para%global_master_reduced_to_slave,-para%ID_total*rve_number+para%ID_global_master_reduced_to_slave,[2,para%nreduced_master_slave])
    
    CALL SMAFloatArrayAccessFortran2D(para%Equations,-para%ID_total*rve_number+para%ID_Equations,[(2+para%ndof_macro),para%nEquations])
    
    CALL SMAIntArrayAccessFortran1D(para%element_to_material,-para%ID_total*rve_number+para%ID_element_to_material,para%nElem)
    
    CALL SMAIntArrayAccessFortran1D(para%global_node_to_slave_node,-para%ID_total*rve_number+para%ID_global_node_to_slave_node,para%nNodes*para%ndof_n)
    
    CALL SMAIntArrayAccessFortran1D(para%perm,-para%ID_total*rve_number+para%ID_perm,para%nRows_reduced)


END SUBROUTINE get_pointer_procedure


SUBROUTINE deallocate_data_procedure(para,rve_number)
    !deallocate the mesh definiting arrays

    CLASS(meshparameters)::para
    INTEGER:: rve_number
        
    CALL SMAFloatArrayDeleteFortran(-para%ID_total*rve_number+para%ID_Equations)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_master_reduced_to_global)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_global_master_reduced_to_slave)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_rowIndex_reduced)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_columnIndex_reduced)
    CALL SMAFloatArrayDeleteFortran(-para%ID_total*rve_number+para%ID_COORDSGLOBAL)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_element_to_global_dof)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_element_to_reduced_dof)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_values_to_global_reduced)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_element_to_material)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_global_node_to_slave_node)
    CALL SMAFloatArrayDeleteFortran(-para%ID_total*rve_number+para%ID_delta_x)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_perm)
    CALL SMAIntArrayDeleteFortran(-para%ID_total*rve_number+para%ID_scalars)
                    
END SUBROUTINE deallocate_data_procedure

SUBROUTINE To_upper(str)
   !this subroutine converts a string with upper and lower cases to a purely
   !upper case expression
     CHARACTER(*), INTENT(IN OUT) :: str
     INTEGER :: i
 
     DO i = 1, LEN(str)
       SELECT CASE(str(i:i))
         CASE("a":"z")
           str(i:i) = ACHAR(IACHAR(str(i:i))-32)
       END SELECT
     END DO 
END SUBROUTINE To_upper

END MODULE type_meshparameters
