Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Error Extending Array

EmmaTraversy
Beginner
2,069 Views

Dear All

I am trying to write a Fortran subroutine (which is consisted of several subroutines) for Abaqus. In a part of it:

I am passing an existing element list (which is a 2d array (n,2) ) to another subroutine and try to extend it (it will read files but I tried to do simple case first and try to extend a 3x2 array to 5x2array):

INTEGER, DIMENSION(:,:), ALLOCATABLE :: MYELLIST

ALLOCATE(MYELLIST(3,2))

...

CALL TEST_SUBROUTINE(MYELLIST,KN)

KN is the current size so that we can dimension the MYELLIST array on the 2nd subroutine:

SUBROUTINE TEST_SUBROUTINE(MYELLIST,KN)

...

INTEGER, DIMENSION(:,:), ALLOCATABLE :: TEMPLIST
DIMENSION MYELLIST(KA,2)

...

I tried to define a TEMPLIST with the proper size (extending KA with +KB = 5 here in simple case) and first copy the MYELLIST into it and after that add additional values:

ALLOCATE(TEMPLIST(KA+KB,2))
DO i=1,KA
TEMPLIST(i,1) = MYELLIST(i,1)
TEMPLIST(i,2) = MYELLIST(i,2)
ENDDO

...

 

The problem is when I am trying to replace the MYELLIST with TEMPLIST an error will rise:

deallocate(MYELLIST)
call move_alloc(TEMPLIST, MYELLIST)

or even:

deallocate(MYELLIST)
allocate(MYELLIST(5,2))
MYELLIST = TEMPLIST

 

It seems as soon as I deallocate the MYELLIST an error will terminate the job.

It think Abaqus subroutines are limited to Fortran 77 or 90 fixed form.

And I am really a beginner and have very limited knowledge in programming so please forgive me if my question is inconvenient.

Many Thanks in advance

Labels (1)
0 Kudos
12 Replies
Arjen_Markus
Honored Contributor I
2,051 Views

Your code shows an argument KN but a declaration that uses KA. As you do not show the entire routine, this is simply guessing, but could it be that KA is not defined and should instead be KN? You can guard against this sort of things by using the statement "IMPLICIT NONE". It forces you to explicitly declare all variables in your code. That way many typos are easily corrected.

If this is not the case, then it would help if you posted complete code that reproduces the problem - the smaller the better, but sometimes that is quite difficult.

0 Kudos
EmmaTraversy
Beginner
2,039 Views

Dear Arjen-Markus
Unfortunately that is not the problem, I tested the rest of the program and it will run with no errors, but as soon as I try to deallocate the array it will terminate.

I tried to simplified the code, I renamed the variables and contain only the problem part (everything works fine until the deallocation line added):

 

      SUBROUTINE UVARM(UVAR,DIRECT,T,TIME,DTIME,CMNAME,ORNAME,
C
     1 NUVARM,NOEL,NPT,LAYER,KSPT,KSTEP,KINC,NDI,NSHR,COORD,
     2 JMAC,JMATYP,MATLAYO,LACCFLA) 
C
      INCLUDE 'ABA_PARAM.INC'
C
      LOGICAL, SAVE :: FIRSTRUN = .TRUE.
      CHARACTER*80 CMNAME,ORNAME
      CHARACTER*3 FLGRAY(15)
      INTEGER KA
      INTEGER, DIMENSION(:,:), ALLOCATABLE :: MYELLIST
      DIMENSION UVAR(NUVARM),DIRECT(3,3),T(3,3),TIME(2)
      DIMENSION ARRAY(15),JARRAY(15),JMAC(*),JMATYP(*),COORD(*)
C
C test a simple 3x2 array
      MYELLIST(1,1) = 1
      MYELLIST(2,1) = 2
      MYELLIST(3,1) = 3
      MYELLIST(1,2) = 11
      MYELLIST(2,2) = 22
      MYELLIST(3,2) = 33
      KA = 3
      IF (FIRSTRUN) THEN
          ALLOCATE(MYELLIST(3,2))
          CALL TEST_SUB(MYELLIST,KA)
C if this works it should print new values
          WRITE(6,*) MYELLIST
          WRITE(6,*) MYELLIST
          FIRSTRUN = .FALSE.
      ENDIF
C
      RETURN
      END
C    
C----------------------------------------------------------------------
C
      SUBROUTINE TEST_SUB(MYELLIST,KA)
      INTEGER KA, KB, i
      INTEGER, DIMENSION(:,:), ALLOCATABLE :: TEMPLIST
      DIMENSION MYELLIST(KA,2)
C
C at first i just change thee values with same size and its ok
C i got the changed array in the first subroutine
      GRAINID = GRAINID + 1
      MYELLIST(1,1) = 11
      MYELLIST(2,1) = 22
      MYELLIST(3,1) = 33
      MYELLIST(1,2) = 111
      MYELLIST(2,2) = 222
      MYELLIST(3,2) = 333
C
      KB = 2
      ALLOCATE(TEMPLIST(KB+NPLUS,2))
      DO i=1,KA
          TEMPLIST(i,1) = MYELLIST(i,1)
          TEMPLIST(i,2) = MYELLIST(i,2)
      ENDDO
      TEMPLIST(KA+1,1) = 4
      TEMPLIST(KA+1,2) = 44
      TEMPLIST(KA+2,1) = 5
      TEMPLIST(KA+2,2) = 55
C I can read the changed KA (3->5) on the other subroutine
C but i didnt find a way to replace MYELLIST with TEMPLIST
      KA = KA+KB
C      
      deallocate(MYELLIST)
      allocate(MYELLIST(5,2))
      MYELLIST = TEMPLIST
      
C     Or this way:
C     deallocate(MYELLIST)
C     call move_alloc(TEMPLIST, MYELLIST)
C
      RETURN
      END

 

And I believe it is IMPLICIT NONE, because it is will give compilation error if any variable is not defined properly. 


Is there any other way that we can extend an array?
for example we have an existing array then we read several files in a loop and each time add some elements at the end of array?

Thank you

 

0 Kudos
Arjen_Markus
Honored Contributor I
2,029 Views

Hm, what is the exact error message you get?

An alternative would be to rely on automatic reallocation, but that merely hides the deallocation that will take place:

real, allocatable :: a, b

allocate(b(100), a(50))
b = 1.0
a = b ! Automatical reallocation happens because the left-hand side is allocatable

You may get errors regarding deallocation if the array is not actually allocated or if somehow the memory is corrupted. The error messages that are printed on the console/terminal window should tell you what is going wrong. (However, in some environments this is hidden, unfortunately.)

0 Kudos
EmmaTraversy
Beginner
2,019 Views

Thank you for your reply

I got: Problem during compilation, but since it is in Abaqus software I can't find out what is the exact problem.

Everything is okay but as soon as I add:

deallocate(MYELLIST)
call move_alloc(TEMPLIST, MYELLIST)
It will lead to the mentioned error.

------
In the second subroutine, If I just declare it this way:
INTEGER, DIMENSION(:,:), ALLOCATABLE :: MYELLIST
As soon job get to this part of code it will terminate.

So the only way it will work is to define the dimension:
DIMENSION MYELLIST(KA,2)

And I tried your suggestion, unfortunately it wont change the size of array and data written to it will be false

Thanks again

0 Kudos
FortranFan
Honored Contributor II
2,012 Views

@EmmaTraversy ,

Please try with an explicit interface for your TEST_SUB and see if that helps.  I don't know how the build toolchain config with ABAQUS works.  It's possible with TEST_SUB as external procedure, its interface is not visible to your UVARM method (it usually requires a compiler option such as gen-interfaces with Intel compiler).  Hence this suggestion.  Please see below as an option - note it's untested, so excuse any typos.

 

 

 

      SUBROUTINE UVARM(UVAR,DIRECT,T,TIME,DTIME,CMNAME,ORNAME,
C
     1 NUVARM,NOEL,NPT,LAYER,KSPT,KSTEP,KINC,NDI,NSHR,COORD,
     2 JMAC,JMATYP,MATLAYO,LACCFLA) 
C
      INCLUDE 'ABA_PARAM.INC'
C
      LOGICAL, SAVE :: FIRSTRUN = .TRUE.
      CHARACTER*80 CMNAME,ORNAME
      CHARACTER*3 FLGRAY(15)
      INTEGER KA
      INTEGER, DIMENSION(:,:), ALLOCATABLE :: MYELLIST
      DIMENSION UVAR(NUVARM),DIRECT(3,3),T(3,3),TIME(2)
      DIMENSION ARRAY(15),JARRAY(15),JMAC(*),JMATYP(*),COORD(*)
C Add explicit interface for TEST_SUB
      INTERFACE
         SUBROUTINE TEST_SUB(MYELLIST,KA)
C Specify Argument list and make intent clear
            INTEGER, ALLOCATABLE, INTENT(INOUT) :: MYELLIST(:,:)
            INTEGER, INTENT(IN) ::  KA
         END SUBROUTINE
      END INTERFACE
C
C test a simple 3x2 array
      MYELLIST(1,1) = 1
      MYELLIST(2,1) = 2
      MYELLIST(3,1) = 3
      MYELLIST(1,2) = 11
      MYELLIST(2,2) = 22
      MYELLIST(3,2) = 33
      KA = 3
      IF (FIRSTRUN) THEN
          ALLOCATE(MYELLIST(3,2))
          CALL TEST_SUB(MYELLIST,KA)
C if this works it should print new values
          WRITE(6,*) MYELLIST
          WRITE(6,*) MYELLIST
          FIRSTRUN = .FALSE.
      ENDIF
C
      RETURN
      END
C    
C----------------------------------------------------------------------
C
      SUBROUTINE TEST_SUB(MYELLIST,KA)
C Specify Argument list and make intent clear
      INTEGER, ALLOCATABLE, INTENT(INOUT) :: MYELLIST(:,:)
      INTEGER, INTENT(IN) ::  KA
C Local variables
      INTEGER KB, i
      INTEGER, ALLOCATABLE :: TEMPLIST(:,:)
C
C at first i just change thee values with same size and its ok
C i got the changed array in the first subroutine
      GRAINID = GRAINID + 1
      MYELLIST(1,1) = 11
      MYELLIST(2,1) = 22
      MYELLIST(3,1) = 33
      MYELLIST(1,2) = 111
      MYELLIST(2,2) = 222
      MYELLIST(3,2) = 333
C
      KB = 2
      ALLOCATE(TEMPLIST(KB+NPLUS,2))
      DO i=1,KA
          TEMPLIST(i,1) = MYELLIST(i,1)
          TEMPLIST(i,2) = MYELLIST(i,2)
      ENDDO
      TEMPLIST(KA+1,1) = 4
      TEMPLIST(KA+1,2) = 44
      TEMPLIST(KA+2,1) = 5
      TEMPLIST(KA+2,2) = 55
C I can read the changed KA (3->5) on the other subroutine
C but i didnt find a way to replace MYELLIST with TEMPLIST
      KA = KA+KB
C      
      deallocate(MYELLIST)
      allocate(MYELLIST(5,2))
      MYELLIST = TEMPLIST
      
C     Or this way:
C     deallocate(MYELLIST)
C     call move_alloc(TEMPLIST, MYELLIST)
C
      RETURN
      END

 

 

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,929 Views

FWIW

Your upper level subroutine UVARM is writing to individual cells of the unallocated MYELLIST array, then performing an ALLOCATE on this array. As to why this did not error out, I cannot say. Also, as to why you observe the initial values (written to the unallocated and prior to allocation) is more perplexing.

Have you run this with full runtime diagnostics?

Jim Dempsey

0 Kudos
andrew_4619
Honored Contributor II
1,972 Views

deallocate(MYELLIST)
call move_alloc(TEMPLIST, MYELLIST)

 

The deallocate above is not needed. The move_alloc makes mylist point at templist data and will "deallocate" templist automatucally so only Myellist then exists. I have not tested but in all my usage cases of move_alloc both arrays are allocated at the time of the move_alloc. It would seem pointless for this not to be so and I would imagine it my be a requirement. 

0 Kudos
Steve_Lionel
Honored Contributor III
1,961 Views

It is not a requirement that the TO array be allocated, but if it is, it is automatically deallocated.

0 Kudos
EmmaTraversy
Beginner
1,947 Views

@FortranFan 
Thank you for your reply. It did not work at first try but I will put more effort on it in the next days.

@Steve_Lionel , @andrew_4619 

Thanks you for your replies.
I tried without deallocation and still got compilation error.

All the Help documents in Abaqus have subroutines written in F77, and I think by default it forces the code to compile with F77 compiler. The error is maybe because MOVE_ALLOC is supported in Fortran 2003 and later. I believe it is possible to extend compiler options in Abaqus to recognize and compile newer versions.

I have no knowledge so excuse me if my words don't make any sense, but another thing that may caused the error is parallel running of subroutines in several nodes.

But I will try more in the next days.
Thank you very much for your replies.

Regards

Emma

0 Kudos
andrew_4619
Honored Contributor II
1,941 Views

what compiler (specific version) are you using?

what is the compiler error? exact error message? There is quite a bit of guesswork going on with many of the answers people are making because the basics of the problem lack definition. A compiler error is normally a very simple matter to diagnose and fix, Fortran has well defined rules.

0 Kudos
andrew_4619
Honored Contributor II
1,919 Views

C:\test>ifort /c uvarm.for
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.1 Build 20201112_000000
Copyright (C) 1985-2020 Intel Corporation. All rights reserved.

uvarm.for(6): error #5102: Cannot open include file 'ABA_PARAM.INC'
INCLUDE 'ABA_PARAM.INC'
--------------^
uvarm.for(67): error #6724: An allocate/deallocate object must have the ALLOCATABLE or POINTER attribute. [MYELLIST]
deallocate(MYELLIST)
-----------------^
uvarm.for(68): error #6724: An allocate/deallocate object must have the ALLOCATABLE or POINTER attribute. [MYELLIST]
allocate(MYELLIST(5,2))
---------------^
compilation aborted for uvarm.for (code 1)

Well the first error is that I don't have the include file but the other two errors are quite clear.

0 Kudos
Steve_Lionel
Honored Contributor III
1,921 Views

@EmmaTraversy 

Re: "All the Help documents in Abaqus have subroutines written in F77, and I think by default it forces the code to compile with F77 compiler."

This is not the case. F77 code is also F2018 code (with rare exceptions), and there is no "F77 compiler" that you have. 

Please show a small but complete example demonstrating the error and give us the full text of the error message (along with the line it is complaining about.)

0 Kudos
Reply