Jeff Faraci
Jeff Faraci

Reputation: 413

passing a truncated size array into subroutine

I am trying to implement periodic boundary conditions on a PDE using ghost cells. I've updated the post with a more detailed sample code.

module Example
  integer, parameter :: nx = 10, ny = 10

contains
  subroutine Subrt(func)
    implicit none
    real, dimension(-nx:nx, -ny:ny), intent(inout) :: func
    real, dimension(-nx:nx, -ny:ny) :: func1
    real, dimension(-nx:nx, -ny:ny) :: Gfunc0, Gfunc1

    Gfunc0 = Deriv(func)
    func1 = func + Gfunc0
    Gfunc1 = Deriv(func1)
  end subroutine Subrt

  function Deriv(func)
    implicit none
    integer :: i,j
    real, dimension(-nx-1:nx,-ny-1:ny) :: func, Deriv

    do j = -ny,ny-1
      do i = -nx,nx-1
        deriv(i,j) = func(i+1,j) + func(i-1,j)
      end do 
    end do

    !imposing periodicity on the gradient
    deriv(-nx-1,:) = deriv(nx-1,:)
    deriv(nx,:)    = deriv(-nx,:)
    deriv(:,-ny-1) = deriv(:,ny-1)
    deriv(:,ny)    = deriv(:,-ny)
  end function Deriv 
end module Example

!I now define the function func, initial and boundary conditions and run the code:
program MyTest
  use Example
  implicit none      
  real, dimension(-nx-1:nx,-ny-1:ny) :: func
  integer :: i,j

  do i = -nx,nx-1
    do j = -ny,ny-1
      func(i,j) = ...
    end do
  end do

  !Impose periodicity
  func(-nx-1,:) = func(nx-1,:)
  func(nx,:)    = func(-nx,:)
  func(:,-ny-1) = func(:,ny-1)
  func(:,ny)    = func(:,-ny)

  call Subrt(func) !problem arises when I call subroutine here
end program

So the 'ghost cells' are the array elements -nx-1, -ny-1. I use these points to connect to impose periodicity.

The problem I have is when I use this function func to pass into my subroutine. My subroutine that solves the differential equation only acts on the physical system size, from

 (-nx:nx,-ny:ny)

so when I call the function func to pass into my subroutine,

I am getting the follow warning and error message:

 Actual argument contains too few elements for dummy argument
 Different shape for array assignment

Is there a way to call the function func into the subroutine by truncating the array elements (-nx-1,-ny-1)? I want to pass only a part of my function array func, (-nx:nx,-ny:ny) into the subroutine, instead of calling the whole function array which includes the ghost points that yields this warning/error message. However, I'm unsure of how to call the truncated array.

Upvotes: 1

Views: 204

Answers (2)

BenBoulderite
BenBoulderite

Reputation: 336

As pointed by Rodrigo Rodrigues, the dimensions of the array manipulated my the main program, Subrt and Deriv are inconsistent.

An easy fix is to change variable declaration in Subrt:

subroutine Subrt(func)
implicit none
real, dimension(-nx-1:nx, -ny-1:ny), intent(inout) :: func
real, dimension(-nx-1:nx, -ny-1:ny) :: func1
real, dimension(-nx-1:nx, -ny-1:ny) :: Gfunc0, Gfunc1

The code now compiles and runs.

It seems to me easier to consistently pass the full array within the different elements of the program (and to ignore some elements), rather than passing as arguments arrays of variable size. (In particular, if you truncate only one row or one column, I don't see any benefit that would compensate the book-keeping generated by slicing.)

Upvotes: 1

Rodrigo Rodrigues
Rodrigo Rodrigues

Reputation: 8576

Your code doesn't seem to make sense so far... and it still not clear what are you trying to achieve.

In the main program, you declare an array func with shape (-11:10, -11:10) - that are 22x22 elements - and pass it as an actual argument to the subroutine Subrt, which declares a dummy argument also named func, but with an explicit shape (-10:10, -10:10) - that is 21x21 elements.

So far so good, only the first 21x21 elements of your func array are really passed to the subroutine, and rebounded such that the element of index (-11, -11) of the actual argument is mapped to the element (-10, -10) of the dummy argument, and so on, until the element (9, 9) of the actual argument is mapped to the last element (10, 10) of the dummy argument.

Is there a way to call the function func into the subroutine by truncating the array elements (-nx-1,-ny-1)? I want to pass only a part of my function array, func, (-nx:nx,-ny:ny) into the subroutine (...)

Passing a section of an array is really easy. The following will pass only (-nx:nx,-ny:ny) - a 21x21 elements subset - to the subroutine:

call Subrt(func(-nx:nx, -ny:ny))

And the mapping will be (-10, 10) of the actual argument to the (-10, 10) of the dummy argument, and so on.

But this will not help you with the following problem... Inside Subrt, you try to pass this array as an actual argument to the Deriv function, that is expecting a (-11:10, -11:10) shape array - that is 22x22 elements. The error comes from here.

Actual argument contains too few elements for dummy argument. Different shape for array assignment

The procedure Subrt expects an array larger than the one you are passing.

Upvotes: 2

Related Questions