.. SPDX-FileCopyrightText: 1992-2026 NWO-I/SRON Space Research Organisation Netherlands .. .. SPDX-License-Identifier: CC-BY-4.0 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 --------------------- .. list-table:: :widths: 20 30 50 :header-rows: 1 * - 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 -------------------- .. list-table:: :widths: 20 30 50 :header-rows: 1 * - 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** .. function:: memo_i1(a, n1) Allocate or resize 1D integer array :param a: Allocatable integer array (integer, dimension(:), allocatable) :param n1: Size of first dimension (integer) :return: None Allocates if not allocated, resizes if size changes, initializes to 0. .. function:: memo_i2(a, n1, n2) Allocate or resize 2D integer array :param a: Allocatable integer array (integer, dimension(:,:), allocatable) :param n1: Size of first dimension (integer) :param n2: Size of second dimension (integer) :return: None .. function:: memo_i3(a, n1, n2, n3) Allocate or resize 3D integer array :param a: Allocatable integer array (integer, dimension(:,:,:), allocatable) :param n1: Size of first dimension (integer) :param n2: Size of second dimension (integer) :param n3: Size of third dimension (integer) :return: None **Real Array Allocation** .. function:: memo_r1(a, n1) Allocate or resize 1D real array :param a: Allocatable real array (real(dp), dimension(:), allocatable) :param n1: Size of first dimension (integer) :return: None Allocates if not allocated, resizes if size changes, initializes to 0.0. .. function:: memo_r2(a, n1, n2) Allocate or resize 2D real array :param a: Allocatable real array (real(dp), dimension(:,:), allocatable) :param n1: Size of first dimension (integer) :param n2: Size of second dimension (integer) :return: None .. function:: memo_r3(a, n1, n2, n3) Allocate or resize 3D real array :param a: Allocatable real array (real(dp), dimension(:,:,:), allocatable) :param n1: Size of first dimension (integer) :param n2: Size of second dimension (integer) :param n3: Size of third dimension (integer) :return: None **Character Array Allocation** .. function:: memo_a1(a, n1) Allocate or resize 1D character array :param a: Allocatable character array (character*(*), dimension(:), allocatable) :param n1: Size of first dimension (integer) :return: None Allocates if not allocated, resizes if size changes. **Memory Management Common Block** .. code-block:: fortran 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** .. code-block:: fortran 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** .. code-block:: fortran 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** .. code-block:: fortran 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** .. code-block:: fortran 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** .. code-block:: fortran 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** .. code-block:: fortran 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** .. code-block:: fortran 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** .. code-block:: fortran ! 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 -------- - :doc:`../core/constants` - Mathematical constants for array calculations - :doc:`../data/lists` - Alternative data structures for dynamic collections - :doc:`../core/messages` - Error reporting for memory issues