0

I have a number of variables declared in a module such as

module test

use othermod, only: n

integer, dimension(n) :: var0
real, dimension(n) :: var1
real, dimension(n) :: var2
..... 
real, dimension(n) :: var1000

end module test

Then I have a subroutine that fills these variables with values. At this point I would like to create an array of arrays with all the variables declared in module test so that I can easily copy or print all variables of a particular (n) at the same time, like dimension(n,allvariablesin module test). For example I would like to do something like array(3,:)=array(2,:). Because this code is part of a very large program I cannot really modify too much, but rather I need to create an array of arrays from all the variables in this module without typing all the variables. How can I easily integrate this change in the current code?

6
  • 1
    Create a derived type and store them there. Or store there pointers to these. There are no arrays of arrays in Fortran. Commented Aug 12, 2016 at 21:42
  • I agree with @VladimirF. Please note that every variable declaration inside a module automatically inherits the save attribute. If you want different instances of var0, var1, var2, ..., var1000 arrays for different values of n you must enclose the variables as type-components inside a derived data type. Commented Aug 13, 2016 at 1:20
  • There is a structure of arrays, but why? If USE TEST in you routines and functions then you get them all showing up there. array(3,:)=array(2,:) is not that much of a time saver over var1(:) = var2(:). If var1 is Mass and var2 is weight, then it becomes easier to understand than massweight(1,:) being mass and massweight(2,:) being weight. If var1 is X-Axis and Var2 is Y-Axis then xy(:,:) makes sense as a 2D array... Otherwise keeping them as arrays might make more sense? Commented Aug 13, 2016 at 1:28
  • @Holmz Since modules automatically inherit the save attribute, such an approach is not thread-safe, i.e., you're note allowed you to create multiple instances of var0, var1, ..,var1000 in the same code. Commented Aug 13, 2016 at 2:28
  • @Holmz I don't understand your point, with your suggestion, to copy all variables with position x to position y I would have to type all variable names, with a different structure I could just assign all variables in position x to position y. Each array has the same exact length. Commented Aug 13, 2016 at 10:15

1 Answer 1

1

I urge you follow to @Vladimir F's advice and encapsulate your variables inside a derived data type. You can employ the associate construct to call old codes expecting var0, var1, .., etc. Lastly, we can overload the type's name to get a Java style constructor in the code below

module type_MyArray

  implicit none
  private

  type, public :: MyArray
     ! type-components
     real, dimension(:), allocatable :: var0, var1, var2
   contains
     ! type-bound procedures
     procedure :: create => create_my_array
     procedure :: destroy => destroy_my_array
  end type MyArray

  interface MyArray
     module procedure my_array_constructor
  end interface MyArray

contains

  pure function my_array_constructor(n) result (return_value)
    ! Dummy arguments
    integer, intent (in) :: n
    type (MyArray)       :: return_value

    call return_value%create(n)

  end function my_array_constructor


  pure subroutine create_my_array(self, n)
    ! Dummy arguments
    class(MyArray), intent(in out) :: self
    integer,        intent(in)     :: n

    allocate( self%var0(n) )
    allocate( self%var1(n) )
    allocate( self%var2(n) )

  end subroutine create_my_array


  pure subroutine destroy_my_array(self)
    ! Dummy arguments
    class(MyArray), intent(in out) :: self

    if (allocated(self%var0)) deallocate( self%var0 )
    if (allocated(self%var1)) deallocate( self%var1 )
    if (allocated(self%var2)) deallocate( self%var2 )

  end subroutine destroy_my_array

end module type_MyArray

program main

  use type_MyArray, only: MyArray
  use old_code,     only: do_something

  implicit none

  type (MyArray) :: foo, bar

  ! Allocate memory
  foo = MyArray(42)
  bar = MyArray(4200)

  associate( var0 => foo%var0, var1 => bar%var1 )

    ! Call old code using var0 and var1
    call do_something(var0, var1)

  end associate

  ! Release memory
  call foo%destroy()
  call bar%destroy()

end program main
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for this solution, I am not that savvy with fortran so I will have to understand how all this works. What I forgot to mention is that I don't need to substitute the old variables, those will remain in place, does this make things easier. This new type will only be added to the code. So in the data type I can have integer, real and logical all together?
I suggest that you brush up on object-oriented software design and good Fortran practices. You might find the following link useful fortran90.org

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.