# Redimensioning local array based upon passed array

**URL:** <https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824>\
**Category:** Help\
**Created:** [November 29, 2022, 10:36am UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824 "2022-11-29T10:36:15Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![garynewport](https://avatars.discourse-cdn.com/v4/letter/g/898d66/32.png) [@garynewport](https://fortran-lang.discourse.group/u/garynewport)\
**Post date:** [November 29, 2022, 10:36am UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/1 "2022-11-29T10:36:15Z")

</div>

I have a subroutine that takes two different size arrays as input.

I have currently set this up as follows:

```auto
	subroutine copacity(t, rho, realk, rkapparef, rhoref, tref, its, irhs)
	    
	    implicit none
	    
	    double precision :: realk, rho, t, rhoref(irhs), tref(its), rkapparef(irhs, its)
	    integer :: irhs, its
	    
	    save

		ALL CODE HERE
		
		return
	end subroutine

```

The two final parameters (`its` and `irhs`) are simply the dimensions of the arrays.

I cannot appear to define the arrays ‘on the fly’ as such; I have to have the parameters. I originally thought that passing the arrays would cause the system to define the local arrays accordingly, but this is not the case. I could define a single parameter, that defines which case to use (there are only two potential arrays that could be passed), but then I cannot use an `if` statement to select the relevant integer values, prior to the arrays being defined.

Is there a method by which the local array could easily be set to the dimensions of the passed array?  
Or is the passing of the two integer dimensions the best (only) approach?

---

<div class="post-metadata">

**Author:** ![conradoat](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/conradoat/32/1537_2.png) [@conradoat](https://fortran-lang.discourse.group/u/conradoat)\
**Post date:** [November 29, 2022, 10:48am UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/2 "2022-11-29T10:48:23Z")

</div>

Use the function size.

> **[SIZE - The GNU Fortran Compiler](https://gcc.gnu.org/onlinedocs/gcc-4.6.4/gfortran/SIZE.html)**
>
> The GNU Fortran Compiler

---

<div class="post-metadata">

**Author:** ![conradoat](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/conradoat/32/1537_2.png) [@conradoat](https://fortran-lang.discourse.group/u/conradoat)\
**Post date:** [November 29, 2022, 10:48am UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/3 "2022-11-29T10:48:55Z")

</div>

its=size(tref)

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [November 29, 2022, 11:18am UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/4 "2022-11-29T11:18:55Z")

</div>

If you want to get rid of integer parameters to pass the dimensions of an argument-array, you need to use _assumed-shape_ mechanism. You then declare the argument-arrays using colons (one for each dimension), as in:  
`double precision :: rhoref(:), tref(:), rkapparef(:,:)`

But this **requires** the procedure (here, your subroutine) to have **explicit interface** in the program segment where it gets called.

Then, you can declare local arrays in one of two ways: as automatic or allocatable arrays. Automatic arrays cannot be saved, however, they are created on every entry to the subroutine and destroyed on exit. Allocatable local arrays are deallocated on exit if not saved. So if you want your local arrays to be also saved, use allocatables but be aware that the subroutine would have to be called with arrays of the same shape to stay consistent with the allocatable locals.

```fortran
program m
  implicit none
  interface
    subroutine copacity(t, rho, realk, rkapparef, rhoref, tref)
      double precision :: realk, rho, t
      double precision :: rhoref(:), tref(:), rkapparef(:,:)
    end subroutine copacity
  end interface
  ! [...]
  call copacity(...)
  ! [...] 
end program m
subroutine copacity(t, rho, realk, rkapparef, rhoref, tref)
  implicit none
  double precision :: realk, rho, t
  double precision :: rhoref(:), tref(:), rkapparef(:,:) ! assumed shape argument-arrays
  double precision :: auto_tref(size(tref)) ! automatic local
  double precision :: auto_rkappa(size(rkapparef,1),size(rkapparef,2)) ! automatic local
  double precision, allocatable :: all_rkappa(:,:), all_tref(:) ! allocatable local
! [...]
  if (.not. allocated(all_rkappa)) allocate(all_rkappa, mold=rkapparef)
  if (.not. allocated(all_tref)) allocate(all_tref, mold=tref)
! [...]
end subroutine copacity

```

---

<div class="post-metadata">

**Author:** ![garynewport](https://avatars.discourse-cdn.com/v4/letter/g/898d66/32.png) [@garynewport](https://fortran-lang.discourse.group/u/garynewport)\
**Post date:** [November 29, 2022, 11:22am UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/5 "2022-11-29T11:22:52Z")

</div>

The destruction, or not, of the array is not of concern (I believe). However, I was led to believe that the allocatable approach would only work on the first dimension of a 2D array; that the second dimension had to be a fixed value?

I’m trying the size trick first; see how that comes out. 🙂

---

<div class="post-metadata">

**Author:** ![garynewport](https://avatars.discourse-cdn.com/v4/letter/g/898d66/32.png) [@garynewport](https://fortran-lang.discourse.group/u/garynewport)\
**Post date:** [November 29, 2022, 11:50am UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/6 "2022-11-29T11:50:25Z")

</div>

I did this…

```auto
	subroutine copacity(t, rho, realk, rkapparef, rhoref, tref)
	    
	    implicit none
	    
	    integer :: icool, ihot, irhs = size(rhoref), iterx, its = size(tref), jdense, jrare, mode
	    double precision :: condmin, dense, rare, realk, rho, t, rhoref(irhs), tref(its), rkapparef(irhs, its)
	    character(8) :: term
	    
	    save

	    SOME CODE HERE
	    return
	end subroutine

```

However, this generated a whole series of errors; primarily caused by this…

```auto
stelcor.f90:5439:53:

 5439 | subroutine copacity(t, rho, realk, rkapparef, rhoref, tref)
      | 1
Error: Symbol ‘rhoref’ at (1) has no IMPLICIT type
stelcor.f90:5444:73:

 5444 | double precision :: condmin, dense, rare, realk, rho, t, rhoref(irhs), tref(its), rkapparef(irhs, its)
      | 1
Error: Symbol ‘irhs’ at (1) has no IMPLICIT type; did you mean ‘rho’?
stelcor.f90:5444:84:

 5444 | double precision :: condmin, dense, rare, realk, rho, t, rhoref(irhs), tref(its), rkapparef(irhs, its)
      | 1
Error: Symbol ‘its’ at (1) has no IMPLICIT type

```

So, using size as I have hasn’t worked.  
Did I misunderstand?

---

<div class="post-metadata">

**Author:** ![conradoat](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/conradoat/32/1537_2.png) [@conradoat](https://fortran-lang.discourse.group/u/conradoat)\
**Post date:** [November 29, 2022, 12:03pm UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/7 "2022-11-29T12:03:35Z")

</div>

I would follow the suggestion from @msz. You can find there how to use the size function.

---

<div class="post-metadata">

**Author:** ![conradoat](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/conradoat/32/1537_2.png) [@conradoat](https://fortran-lang.discourse.group/u/conradoat)\
**Post date:** [November 29, 2022, 12:08pm UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/8 "2022-11-29T12:08:30Z")

</div>

Here you have another example

> <https://stackoverflow.com/questions/14750572/passing-array-length-to-function>

---

<div class="post-metadata">

**Author:** ![conradoat](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/conradoat/32/1537_2.png) [@conradoat](https://fortran-lang.discourse.group/u/conradoat)\
**Post date:** [November 29, 2022, 12:12pm UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/9 "2022-11-29T12:12:02Z")

</div>

I would just declare

integer :: irhs  
real(kind=real64), dimension(🙂 :: rhoref

and then, in the code

irhs = size(rhoref)

---

<div class="post-metadata">

**Author:** ![JohnCampbell](https://avatars.discourse-cdn.com/v4/letter/j/5daacb/32.png) [@JohnCampbell](https://fortran-lang.discourse.group/u/JohnCampbell)\
**Post date:** [November 29, 2022, 12:22pm UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/10 "2022-11-29T12:22:02Z")

</div>

Adapted from other examples, here is a very cut down example of what is required:

```auto
      Function test( x ) Result( sum_sq )
        Real :: sum_sq
        Real, Dimension( : ), Intent( In ) :: x
        Real, Dimension( size(x) ) :: y

        y = x
        sum_sq = dot_product ( x, y )

      End Function test

```

Test needs an explicit interface or be contained.

---

<div class="post-metadata">

**Author:** ![Harper](https://avatars.discourse-cdn.com/v4/letter/h/b5ac83/32.png) [@Harper](https://fortran-lang.discourse.group/u/Harper)\
**Post date:** [November 29, 2022, 8:41pm UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/11 "2022-11-29T20:41:10Z")

</div>

I used to have trouble like yours. I would now write

```auto
double precision :: realk, rho, t, rhoref(:), tref(:), rkapparef(:,:)

```

instead of

```auto
double precision :: realk, rho, t, rhoref(irhs), tref(its), rkapparef(irhs, its)

```

because those `:` tell the dummy arguments to use the actual argument upper bounds, If you don’t want the lower bound to be 1 you must say what it is, e.g. ` a(0:)` to start at 0.

Note that you may mislead Fortran users by calling arguments parameters, because PARAMETER is used when declaring a constant in Fortran, e.g.

```auto
real,parameter:: pi = 4.0*atan(1.0) 

```

Unfortunately some other languages call an argument a parameter.

It’s also a good idea to use `intent(in)` or `intent(out)` or `intent(inout)` when specifying dummy arguments.

---

<div class="post-metadata">

**Author:** ![PierU](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/pieru/32/1848_2.png) [@PierU](https://fortran-lang.discourse.group/u/PierU)\
**Post date:** [November 29, 2022, 9:11pm UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/12 "2022-11-29T21:11:08Z")

</div>

```auto
subroutine copacity(t, rho, realk, rkapparef, rhoref, tref)	    
implicit none
double precision :: realk, rho, t, rhoref(:), tref(:), rkapparef(:, :) 
          
double precision :: aaa(size(rhoref)), bbb(size(rhoref),size(tref)) ! automatic arrays
double precision, allocatable :: ccc(:), ddd(:,:)

integer :: irhs, its

irhs = size(rhoref)
its = size(its)

allocate( ccc(irhs), ddd(irhs,its) ) ! allocatable arrays
...
		
end subroutine

```

---

<div class="post-metadata">

**Author:** ![garynewport](https://avatars.discourse-cdn.com/v4/letter/g/898d66/32.png) [@garynewport](https://fortran-lang.discourse.group/u/garynewport)\
**Post date:** [December 7, 2022, 1:47pm UTC](https://fortran-lang.discourse.group/t/redimensioning-local-array-based-upon-passed-array/4824/13 "2022-12-07T13:47:01Z")

</div>

Thanks for all the replies. I went for the `tref(:)` etc approach and this worked fantastically. I then used the `size` to set the other two variables, which also worked. I was then able to tidy up the variables, reducing the overall number by 2, marked the inputs with `intent` and converted the subroutine into a function. Just testing now but this seems to have worked well.

Once confirmed I will document what I have done and move on to the next subroutine. 3 down; 26 to go! Hahahaha!
