2.1.23 Allocatable arrays

Products: Abaqus/Standard  Abaqus/Explicit  Abaqus/CFD  

Reference

Overview

To facilitate data accumulation and transfer between user subroutines, users can use utility functions to create their own dynamic storage in the form of allocatable arrays. Thread-local and global arrays are supported.

Any number of thread-local or global arrays can be created. Each array is given an identifier at the time of creation (an arbitrary integer, chosen by the user). The idea behind these identifiers is that the arrays can be created in one user subroutine and referenced in another simply by asking for an array by its identifier. The arrays persist in memory until explicitly deleted by the user or until the analysis terminates.

Thread-local arrays

A thread-local array is a mechanism to allocate storage that is local to a thread and does not need any locking for access. In a multi-threaded environment the thread safety of these arrays stems from their design and usage: they are deliberately not shared and, thus, do not need to be protected from competing threads. In fact, one thread cannot reference a local array of another thread. They can be accessed concurrently without any locking and, thus, are faster than global arrays.

Thread-local arrays are unique in each thread. They are nonintersecting and nonoverlapping in memory, with each thread starting out with its own private copy of an array. For example, Thread 0 can have a local array with ID 1 and Thread 4 can have a local array with ID 1. Those two arrays are different and separate from each other. Similarly, it is possible to have an integer array with ID 1 and a float array with ID 1. Again, they are two different arrays. It is not possible to cross-reference these arrays across different threads. However, all user subroutines running in one thread can access all arrays of that thread. In a thread-agnostic way, these arrays are shared between user subroutines but not among threads. These routines are meant as a thread-safe replacement for COMMON BLOCKs and SAVE variables.

The following utility subroutines are available to operate on thread-local arrays:

  • SMALocalIntArrayCreate, SMALocalFloatArrayCreate: to create or resize a local array.

  • SMALocalIntArrayAccess, SMALocalFloatArrayAccess: to locate an existing local array.

  • SMALocalIntArrayDelete, SMALocalFloatArrayDelete: to delete a local array.

  • SMALocalIntArraySize, SMALocalFloatArraySize: to get the size of the array.

These utility routines are accessible from both FORTRAN and C/C++. The details of their interfaces are described below.

Global arrays

Global arrays are visible and accessible from all threads in an executable. To prevent race conditions, write access to these arrays from multiple threads must be protected by mutexes (mutual exclusion locks). Using mutexes on every access will incur a performance penalty. In some situations it is possible to avoid unneccessary locking by restricting all threads to operate on nonintersecting ranges of a global array. Another alternative is to use thread-local arrays.

The following utility routines are available to operate on global arrays:

  • SMAIntArrayCreate, SMAFloatArrayCreate: to create or resize a global array.

  • SMAIntArrayAccess, SMAFloatArrayAccess: to locate an existing global array.

  • SMAIntArrayDelete, SMAFloatArrayDelete: to delete a global array.

  • SMAIntArraySize, SMAFloatArraySize: to get the size of the global array.

These arrays are global and accessible from all threads within a process but not across different MPI processes. To share data between separate MPI processes, MPI facilities must be used. Abaqus supports the full use of MPI within user subroutines.


SMALocalIntArrayCreate, SMALocalFloatArrayCreate

Interface

FORTRAN:

      INTEGER*8 SMALocalIntArrayCreate(ID,SIZE)
      INTEGER*8 SMALocalFloatArrayCreate(ID,SIZE)

Example:

#include <SMAAspUserSubroutines.hdr>

      integer a(100)
      pointer(ptra,a)

      ! create a local array with ID=1 and SIZE=100
      ptra = SMALocalIntArrayCreate(1,100) 

      a(1) = 11  ! use as a native Fortran array
      a(2) = 22  ! use as a native Fortran array



C++: 

       #include <SMAAspUserSubroutines.h>

       // Create a local integer array of with ID=1 and size=100
       int* a = SMALocalIntArrayCreate(1,100); 
       // Create an integer array of with ID=2, size=20, and 
       // initial value = -1
       int* b = SMALocalIntArrayCreate(2,100,-1);   

NOTE: Float Arrays can store both SINGLE PRECISION 
      and DOUBLE PRECISION numbers. Internally, 
      memory is allocated in units of 64 bits (double/real*8).

NOTE: To resize an array, simply call Create() with the same ID, 
      but give it a new SIZE parameter. If the new size is larger, 
      the old data are copied over to the new array. No data are lost 
      during resizing.

For example:

      ! resize array with ID=1 to 300 integers
      ptra = SMALocalIntArrayCreate(1,300)  

NOTE: In Create() functions, there is an optional third argument -- 
      intial value. If not supplied, all Int arrays are
      initialized with INT_MAX ( 2,147,483,647 ). All Float Arrays 
      are initialized with signaling NANs.  The values of INT_MAX
      and signaling NANs are accessible via the 'SMAAspNumericLimits.h'
      and 'SMAAspNumericLimits.hdr' header files.

Variables to be provided to the utility routine

ID

Arbitrary number (integer), selected by the user. This number is used to open/reference this array in any other user subroutine.

SIZE

Size of the array as the number of ints or doubles. The maximum size for thread-local arrays is INT_MAX (2,147,483,647).

Variable returned from the utility routine

INTEGER*8 ( address )

Returns a pointer to the array created. This pointer can be associated with a native FORTRAN array or native C/C++ array. Each thread will receive a different pointer. Each thread will create and hold its own array. For example, Array(1) in Thread 0 is separate from Array(1) in Thread 4. These arrays are nonoverlapping and nonintersecting in any way.


SMALocalIntArrayAccess, SMALocalFloatArrayAccess

Interface

Fortran interface:

      INTEGER*8 SMALocalIntArrayAccess(ID)
      INTEGER*8 SMALocalFloatArrayAccess(ID)

Example:

#include <SMAAspUserSubroutines.hdr>

      integer a(100)
      pointer(ptra,a)

C Locate local Array(1) and associate a native array pointer with it

      ptra = SMALocalIntArrayAccess(1) 
      
      a(1) = 11 ! use as a native Fortran array
      a(2) = 22 ! use as a native Fortran array

C++ interface: 

      #include <SMAAspUserSubroutines.h>

      // Locate and open array with ID=1
      int* a =  SMALocalArrayIntAccess(1);
     
      a[1] = 11;  // use as a native array
      a[2] = 22;  // use as a native array


NOTE: If a request is made to access an array that has 
      not been created, the function will return 0. 
     

Variable to be provided to the utility routine

ID

ID of the array (an integer), chosen by the user at the time of creation. Using this ID, an array can be opened in any user subroutine.

Variable returned from the utility routine

INTEGER*8 ( address )

Returns a pointer to the array created. This pointer can be associated with a native FORTRAN array or native C/C++ array. Each thread will receive a different pointer. Each thread, as it passes through this code, will create and hold its own array. For example, Array(1) in Thread 0 is a separate array from Array(1) in Thread 4. These arrays are nonoverlapping and nonintersecting in any way.


SMALocalIntArraySize, SMALocalFloatArraySize

Interface

Fortran interface:

      INTEGER*4 SMALocalIntArraySize(ID)
      INTEGER*4 SMALocalFloatArraySize(ID)

Example:

#include <SMAAspUserSubroutines.hdr>

      integer a_size, d_size

C Get the size of Array(1) as the number of INTEGERs
      a_size = SMALocalIntArraySize(1)   

! Get the size of Array(1) as the number of REALs

      d_size = SMALocalFloatArraySize(1) 

      do k=1,a_size
          ... 
      end do

C++:

      #include <SMAAspUserSubroutines.h>

      // Lookup the size of Array(1) as the number of ints

      int a_size = SMALocalIntArraySize(1);   

      // Lookup the size of Array(1) as the number of doubles
      
      int d_size = SMALocalFloatArraySize(1); 

      for(int i=1; i<=size; i++) {
          ...
      }

Variable to be provided to the utility routine

ID

ID of the array (an integer), chosen by the user at the time of creation.

Variable returned from the utility routine

INTEGER*4

Size of the array.


SMALocalFloatArrayDelete, SMALocalFloatArrayDelete

Interface

Fortran interface:

      subroutine SMALocalIntArrayDelete(ID)
      subroutine SMALocalFloatArrayDelete(ID)

Example:

#include <SMAAspUserSubroutines.hdr>

      call SMALocalIntArrayDelete(1) ! Delete Array(1)



C++ interface:

      #include <SMAAspUserSubroutines.h>

      SMALocalIntArrayDelete(1);  // Delete Array(1)

NOTE: Deletion of arrays is optional. All storage allocated 
      for these arrays will be freed when ABAQUS threads 
      terminate (at the very end of the analysis). It is, 
      however, a good programming practice to delete all
      allocations explicitly, especially when they are
      no longer needed, as this will free up memory for something else.

Variable to be provided to the utility routine

ID

ID of the array (an integer), chosen by the user at the time of creation.


SMAIntArrayCreate, SMAFloatArrayCreate

Interface

Fortran interface:

      INTEGER*8 SMAIntArrayCreate(ID,SIZE,INITVAL)
      INTEGER*8 SMAFloatArrayCreate(ID,SIZE,INITVAL)

Example:

#include <SMAAspUserSubroutines.hdr>

      integer a(100)
      pointer(ptra,a)

      ! create a global array with ID=1, SIZE=100 and INITVAL=-1
      ptra = SMAIntArrayCreate(1,100,-1) 

      a(1) = 11  ! use as a native Fortran array
      a(2) = 22  ! use as a native Fortran array

C++ interface: 

       #include <SMAAspUserSubroutines.h>

       // Create an integer array of with ID=1 and size=100
       int* a = SMAIntArrayCreate(1,100); 
       // Create an integer array of with ID=2, size=20, 
       // and initial value=-1
       int* b = SMAIntArrayCreate(2,100,-1);   

NOTE: Float Arrays can store both SINGLE PRECISION and 
      DOUBLE PRECISION numbers. Internally, they
       allocate storage in 64-bit units (double/real*8).

NOTE: To resize an array, simply call Create() with the same ID, 
      but give it a new SIZE parameter. If the size has increased, 
      the old data will be copied over to the new array. 
      No data is lost during resizing.

For example:

      ! resize array with ID=1 to 300 integers
      ptra = SMAIntArrayCreate(1,300)  

NOTE: In Create() functions, there is an optional third argument -- 
      intial value. If not supplied, all Int arrays are initialized 
      with INT_MAX ( 2,147,483,647 ). All Float Arrays are initialized 
      with Signaling NANs.  The values of INT_MAX and signaling NANs 
      are accessible via the 'SMAAspNumericLimits.h' and
      'SMAAspNumericLimit.hdr' header files.

Variables to be provided to the utility routine

ID

Arbitrary integer, selected by the user. This number is used later to open/reference this array in any other user subroutine.

SIZE

Size of the array as the number of ints or doubles. The maximum size is INT_MAX.

Variables returned from the utility routine

INTEGER*8 ( address )

Returns a pointer to the array created. This pointer can be associated with a native Fortran array or native C/C++ array. All threads with see the same address when they try to access this array through its ID.


SMAIntArrayAccess, SMAFloatArrayAccess

Interface

Fortran interface:

      INTEGER*8 SMAIntArrayAccess(ID)
      INTEGER*8 SMAFloatArrayAccess(ID)

Example:

#include <SMAAspUserSubroutines.hdr>

      integer a(100)
      pointer(ptra,a)

C Locate Array(1) and associate a native array pointer with it

      ptra = SMAIntArrayAccess(1) 
      
      a(1) = 11 ! use as a native Fortran array
      a(2) = 22 ! use as a native Fortran array

C++ interface: 

      #include <SMAAspUserSubroutines.h>

      // Locate and open array with ID=1
      int* a =  SMAIntArrayAccess(1);
     
      a[1] = 11;  // use as a native array
      a[2] = 22;  // use as a native array




NOTE: If a request is made to access an array which has 
      not been created, the function will return 0. 
     

Variable to be provided to the utility routine

ID

ID of the array (an integer), chosen by the user at the time of creation. Using this ID, an array can be opened in any user subroutine.

Variable returned from the utility routine

INTEGER*8 ( address )

Returns a pointer to the array, or 0 if an array with the requested ID does not exist. This pointer can be associated with a native Fortran or C/C++ array.


SMAIntArraySize, SMAFloatArraySize

Interface

Fortran interface:

      INTEGER SMAIntArraySize(ID)
      INTEGER SMAFloatArraySize(ID)

Example:

#include  <SMAAspUserSubroutines.hdr>

      integer a_size, d_size

C Get the size of Array(1) as the number of INTEGERs
      a_size = SMAIntArraySize(1)   

! Get the size of Array(1) as the number of REALs

      d_size = SMAFloatArraySize(1) 

      do k=1,a_size
          ... 
      end do

C++ interface:

      #include <SMAAspUserSubroutines.h>

      // Lookup the size of Array(1) as the number of INTS

      int a_size = SMAIntArraySize(1);   

      // Lookup the size of Array(1) as the number of doubles
      
      int d_size = SMAFloatArraySize(1); 

      for(int i=1; i<=d_size; i++) {
          ...
      }

Variable to be provided to the utility routine

ID

ID of the array (an integer), arbitrary chosen by the user at the time of creation.

Variable returned from the utility routine

INTEGER*4

Size of the array.


SMAFloatArrayDelete, SMAFloatArrayDelete

Interface

FORTRAN:

#include <SMAAspUserSubroutines.hdr>

      call SMAIntArrayDelete(1) ! Delete global Array(1)

C++:

      #include <SMAAspUserSubroutines.h>

      SMAIntArrayDelete(1);  // Delete global Array(1)

NOTE: Deletion of arrays is optional. All storage allocated 
      for these arrays will be freed when ABAQUS terminates
      (at the very end of the analysis). It is, however, a good 
      programming practice to delete all allocations explicitly, 
      especially when they are no longer needed, as this will 
      free up memory for use somewhere else.

Variable to be provided to the utility routine

ID

ID of the array (an integer), chosen by the user at the time of creation.