Memory Management (memo)

Module: utils_memo (via memo subroutines)

Overview

Provides smart memory allocation and deallocation routines for arrays of different types and dimensions. Handles automatic resizing and initialization.

Key Features

  • Automatic array allocation and deallocation

  • Smart resizing (reallocates only when size changes)

  • Automatic initialization (zeros for numeric types)

  • Support for 1D, 2D, and 3D arrays

  • Error handling through common block

Supported Array Types

Type Prefix

Data Type

Description

memo_i*

integer

Integer arrays

memo_r*

real(dp)

Double precision real arrays

memo_a*

character(*)

Character arrays

Supported Dimensions

Suffix

Dimensions

Example

*1

1D

memo_r1(array, n1)

*2

2D

memo_r2(array, n1, n2)

*3

3D

memo_r3(array, n1, n2, n3)

API Reference

Subroutines

Integer Array Allocation

memo_i1(a, n1)

Allocate or resize 1D integer array

Parameters:
  • a – Allocatable integer array (integer, dimension(:), allocatable)

  • n1 – Size of first dimension (integer)

Returns:

None

Allocates if not allocated, resizes if size changes, initializes to 0.

memo_i2(a, n1, n2)

Allocate or resize 2D integer array

Parameters:
  • a – Allocatable integer array (integer, dimension(:,:), allocatable)

  • n1 – Size of first dimension (integer)

  • n2 – Size of second dimension (integer)

Returns:

None

memo_i3(a, n1, n2, n3)

Allocate or resize 3D integer array

Parameters:
  • a – Allocatable integer array (integer, dimension(:,:,:), allocatable)

  • n1 – Size of first dimension (integer)

  • n2 – Size of second dimension (integer)

  • n3 – Size of third dimension (integer)

Returns:

None

Real Array Allocation

memo_r1(a, n1)

Allocate or resize 1D real array

Parameters:
  • a – Allocatable real array (real(dp), dimension(:), allocatable)

  • n1 – Size of first dimension (integer)

Returns:

None

Allocates if not allocated, resizes if size changes, initializes to 0.0.

memo_r2(a, n1, n2)

Allocate or resize 2D real array

Parameters:
  • a – Allocatable real array (real(dp), dimension(:,:), allocatable)

  • n1 – Size of first dimension (integer)

  • n2 – Size of second dimension (integer)

Returns:

None

memo_r3(a, n1, n2, n3)

Allocate or resize 3D real array

Parameters:
  • a – Allocatable real array (real(dp), dimension(:,:,:), allocatable)

  • n1 – Size of first dimension (integer)

  • n2 – Size of second dimension (integer)

  • n3 – Size of third dimension (integer)

Returns:

None

Character Array Allocation

memo_a1(a, n1)

Allocate or resize 1D character array

Parameters:
  • a – Allocatable character array (character*(*), dimension(:), allocatable)

  • n1 – Size of first dimension (integer)

Returns:

None

Allocates if not allocated, resizes if size changes.

Memory Management Common Block

integer mode, lu, ier
common /memocom/ mode, lu, ier

* ``mode``: Operation mode (1=allocate, 4=deallocate)
* ``lu``: Logical unit (unused in current implementation)
* ``ier``: Error code (0=success, non-zero=error)

Usage Examples

1D Array Allocation

use utils_cspex, only: dp

real(dp), dimension(:), allocatable :: data_array
integer :: n_elements, ier

! Allocate array for 100 elements
n_elements = 100
call memo_r1(data_array, n_elements)

! Array is now allocated and initialized to 0.0
write(*,*) 'Array size:', size(data_array)
write(*,*) 'First element:', data_array(1)

2D Array with Resizing

use utils_cspex, only: dp

real(dp), dimension(:,:), allocatable :: matrix
integer :: nrows, ncols

! Initial allocation
nrows = 10
ncols = 20
call memo_r2(matrix, nrows, ncols)

! Resize the array
nrows = 15
ncols = 25
call memo_r2(matrix, nrows, ncols)

write(*,*) 'Matrix dimensions:', shape(matrix)

3D Array for Spectral Data

use utils_cspex, only: dp

real(dp), dimension(:,:,:), allocatable :: spectral_cube
integer :: nx, ny, nz

! Allocate 3D array for spectral data
nx = 100  ! Spatial x dimension
ny = 100  ! Spatial y dimension
nz = 1000 ! Spectral dimension

call memo_r3(spectral_cube, nx, ny, nz)

! Array is automatically initialized to 0.0
write(*,*) 'Spectral cube size:', size(spectral_cube)

Integer Array for Counting

integer, dimension(:), allocatable :: counters
integer :: n_bins

! Allocate integer array for histograms
n_bins = 50
call memo_i1(counters, n_bins)

! Array is initialized to 0
counters = counters + 1  ! Increment all counters
write(*,*) 'Total counts:', sum(counters)

Character Array for Labels

character(len=20), dimension(:), allocatable :: labels
integer :: n_labels

! Allocate character array for labels
n_labels = 10
call memo_a1(labels, n_labels)

! Assign labels
labels(1) = 'Energy'
labels(2) = 'Flux'
labels(3) = 'Error'

write(*,*) 'First label:', trim(labels(1))

Error Handling

use utils_cspex, only: dp

real(dp), dimension(:), allocatable :: big_array
integer :: n_elements, ier
integer :: mode, lu
common /memocom/ mode, lu, ier

! Try to allocate very large array
n_elements = 1000000000  ! 1 billion elements
call memo_r1(big_array, n_elements)

! Check for errors
if (ier /= 0) then
   write(*,*) 'Memory allocation failed with error code:', ier
else
   write(*,*) 'Successfully allocated large array'
endif

Automatic Resizing

use utils_cspex, only: dp

real(dp), dimension(:), allocatable :: dynamic_array
integer :: current_size, new_size

! Initial allocation
current_size = 100
call memo_r1(dynamic_array, current_size)

! Fill with data
dynamic_array = 1.0_dp

! Resize to larger array (data is preserved if size increases)
new_size = 200
call memo_r1(dynamic_array, new_size)

! First 100 elements still contain 1.0
write(*,*) 'First element after resize:', dynamic_array(1)
write(*,*) 'New size:', size(dynamic_array)

Notes

Smart Allocation Behavior

  • Already allocated: Checks if array is already allocated

  • Size match: If size matches, does nothing (no reallocation)

  • Size mismatch: Deallocates and reallocates with new size

  • Initialization: Always initializes numeric arrays to 0

Memory Management

  • Uses Fortran’s built-in allocation with stat parameter

  • Automatic cleanup when variables go out of scope

  • No explicit deallocation needed (but available via mode=4)

Performance Considerations

  • Allocation: O(1) for first allocation, O(n) for reallocation

  • Memory: Minimal overhead (just the array data)

  • Speed: Very fast for typical array sizes

  • Fragmentation: May cause memory fragmentation with frequent resizing

Error Handling

  • Sets ier in common block on allocation failure

  • Returns ier=0 on success

  • Does not stop execution on errors

  • Check ier after allocation for large arrays

Limitations

  • Maximum 3 dimensions supported

  • No automatic bounds checking

  • Character arrays not initialized

  • Common block required for error handling

Best Practices

  1. Check allocation status for large arrays

  2. Reuse arrays when possible to avoid reallocation

  3. Pre-allocate known sizes to minimize resizing

  4. Use for temporary arrays that need automatic cleanup

  5. Consider alternatives for very large or persistent data

Comparison with Standard Allocation

! Standard Fortran allocation
if (allocated(array)) deallocate(array)
allocate(array(n), stat=status)
if (status /= 0) stop 'Allocation failed'
array = 0.0

! Equivalent using memo
call memo_r1(array, n)
if (ier /= 0) stop 'Allocation failed'

The memo version is more concise and handles initialization automatically.

See Also