Silverfrost Forums

Welcome to our forums

Implied DO LOOP and SUM Causes Error

8 Aug 2017 8:08 #19960

Good morning, everyone,

I have several implied DO LOOPs in my program. All of them work, except for those where SUM is used, for example:

!   Reshape is used, because implied DO LOOP returns 1D-array
    array=reshape([((sum(arrin(jcoun,kcoun,:),jcoun=1,ndima),kcoun=1,ndima)],shape(array))

It compiles without error, but at runtime an access violation occurs.

Whereas this works just fine:

		DO kcoun=1,ndima 
			DO jcoun=1,ndima
				array(jcoun,kcoun)=sum(arrin(jcoun,kcoun,:))
            END DO
        END DO

Any ideas as to why that is would be greatly appreciated!

8 Aug 2017 9:08 #19961

Why would you want to use RESHAPE? Even if you can get it to work, it is much more difficult to read and surely can't be more efficient.

As it is I get a syntax error on compilation. An Emoticons?!

8 Aug 2017 9:39 #19962

I used RESHAPE, because the implied DO LOOP returns an array with rank=1 (vector), and I need rank 2 (matrix).

8 Aug 2017 9:43 #19963

What I mean is that the code that 'works just fine' is easier to read and understand and is probably more efficient at runtime.

8 Aug 2017 9:47 #19964

It is? Good to know! Because I read somewhere, that implied DO LOOPs are more efficient, than 'normal' ones, so I tried using them, but it's quite a hassle.

8 Aug 2017 10:34 #19965

I recommend that you ignore issues about efficiency particularly whilst you are learning to write in Fortran. Such issues only become of interest when your runtimes become unreasonably long. Concentrate on writing code that is error free, well documented, easy to read and (as far as is reasonable) 'object oriented'.

8 Aug 2017 11:25 #19966

Alright, thanks for the advice!

8 Aug 2017 3:03 #19967

Paul, the compiler (8.1) generates incorrect code when the first argument to RESHAPE is an array constructor rather than an array variable in the following example, which I put together based on viroxa's posts in this thread.

program xreshape
implicit none
integer, parameter :: nx = 5, ny = 4, nz = 3
real,dimension(nx,ny,nz) :: arrin
real, dimension(nx*ny) :: sm
real, dimension(nx,ny) :: sma, smb
integer :: i,j,k
!
do i=1,nx; do j=1,ny; do k=1,nz; arrin(i,j,k)=100*k+10*j+i
   end do; end do; end do
sm = [((sum(arrin(i,j,:)),i=1,nx),j=1,ny)]
sma=reshape(sm,shape(sma))
write(*,10)(sma(i,:),i=1,nx)
smb=reshape([((sum(arrin(i,j,:)),i=1,nx),j=1,ny)],shape(smb))
write(*,*)
write(*,10)(smb(i,:),i=1,nx)
10 format(1x,4F12.1)
end program

The output has the second half incorrect:

        633.0       663.0       693.0       723.0
        636.0       666.0       696.0       726.0
        639.0       669.0       699.0       729.0
        642.0       672.0       702.0       732.0
        645.0       675.0       705.0       735.0

        542.0       542.0       542.0       542.0
        542.0       542.0       542.0       542.0
        542.0       542.0       542.0       542.0
        542.0       542.0       542.0       542.0
        542.0       542.0       542.0       542.0

If /check is used, a spurious subscript error message is generated in line 14.

8 Aug 2017 3:20 #19968

Mecej4

Thanks. I will make a note of this.

8 Aug 2017 4:31 #19969

Here is a shorter example that uses only 2-D and 1-D arrays and exhibits the same compiler bug. The use of RESHAPE is redundant, since the first argument already has the desired shape, but RESHAPE is needed to exhibit the bug.

program xreshape
implicit none
integer, parameter :: nx = 3, ny = 2
real,dimension(nx,ny) :: arrin
real, dimension(nx) :: sma, smb
integer :: i,j
!
do i=1,nx; do j=1,ny; arrin(i,j)=10*j+i
   end do; end do
sma = [(sum(arrin(i,:)),i=1,nx)]
write(*,10)sma
smb=reshape([(sum(arrin(i,:)),i=1,nx)],shape(smb))
write(*,*)
write(*,10)smb
10 format(1x,3F12.1)
end program
8 Aug 2017 4:35 #19970

Mecej4

Thanks again.

11 Aug 2017 3:06 #19989

Whereas this works just fine: DO kcoun=1,ndima DO jcoun=1,ndima array(jcoun,kcoun)=sum(arrin(jcoun,kcoun,:)) END DO END DO

You need to learn about contiguous storage for arrays, which works from left to right. If array 'arrin' is a large array, the performance would not be described as 'fine'. A better arrangement would be : array(jcoun,kcoun)=sum(arrin(:,jcoun,kcoun))

Large could be when the size of array arrin >> 64k, which would span many memory pages.

It is interesting reading your posts, as you use approaches I would not consider (such as RESHAPE). You will learn from this experience, which can be a good approach.

11 Aug 2017 9:31 #19992

Thanks for pointing that out.

I arranged the array this way, because the assignment of arrin required it. nlays could be 1, but could also be 100, depending on user input:

DO icoun=1,nlays
    DO jcoun=1,ndima
        DO kcoun=1,ndima
            arrin(kcoun,jcoun,icoun)=....
        END DO
    END DO
END DO

Since ndima = 4 and that nested loop calculating the sum is only run once, I didn't bother to rearrange the array. Should I?

Please login to reply.