Silverfrost Forums

Welcome to our forums

Why this is forbidden ?

24 Sep 2024 9:46 #31567

I was shocked to lose heck of time to find that neither FTN95 or gFortran allows this code. I declared TYPEd array (the only reason it is TYPEd is because i want arbitrary allocatable number or elements in this 3D matrix and usual method of allocation does not allow that. Below though I put them of same size) and zeroised its elements at the end

type lostPart
  real*4, allocatable, Dimension (:,:) :: Particles
end type lostPart

Type (lostPart) ispecies(0:2)

  do icase=0,2
    allocate (ispecies(icase)%Particles(12,10:20) )
  enddo

  ispecies(:)%Particles(:,:)  = 0

end

FTN95 gives the diagnostics

22537) ispecie(:)%Particles(:,:)  = 0
*** Error 852: The array expression involving the array component 
    particles is invalid, as the components to the left of the '%' are 
    also array-valued

while gFortran diagnoses and SHOWS it like this ('showing is 100x better than saying', proverb says. It is much more clear and specific as opposed to 'general ruling' of FTN95 requiring good knowledge of English language and Fortran rules what 99% of programmers who are mostly not English speaking of course do not know. This simplicity in part is why gFortran for example has 240 variations and versions for all processor types on Linux and FTN95 has not a single one and requires Linux-Windows emulator like Wine)

  11 |   ispecies(:)%Particles(:,:)  = 0
      |  1
Error: Component to the right of a part reference with nonzero rank must not have the ALLOCATABLE attribute at (1)

The same exact thing but zeroising the array 'manually', arranging for it additional DO loop, works with no problem

type lostPart
  real*4, allocatable, Dimension (:,:) :: Particles
end type lostPart

Type (lostPart) ispecies(0:2)

  do icase=0,2
    allocate (ispecies(icase)%Particles(12,10:20) )
  enddo
  do icase=0,2
    ispecies(icase)%Particles(:,:)  = 0
  enddo
end

What is going on ? Putting aside how compilers diagnose the code (which i think FTN95 should also copy and use) , how come both do not allow zeroising first way?

25 Sep 2024 9:24 #31568

I think you a trying to break the Fortran rules. iFort says:

error #6159: A component cannot be an array if the encompassing structure is an array. [PARTICLES]

PS I looked into this a little more. Fortran does not allow direct assignments to all elements in the allocatable array across different objects in a derived type (because the arrays might have different sizes). You cannot directly assign values to a derived type array section as you are tyring to do.

26 Sep 2024 8:14 #31570

Ken, Having different sizes of all arrays (and ideally all components to be allocatable, including for the ispicies too but that failed from start), was exactly the purpose of this derived type. The fact that not allocatable but simply defined ispicies with known sizes defined in declaration somehow prohibited this to work (i did not try to zeroise any 'sections', i tried to zeroise everything

ispecies(:)%Particles(:,:)  = 0

or this where any hints on sections were not mentioned at all

ispecies%Particles  = 0

but by unknown reason allowed this where i do the same thing

  do icase=0,2
    ispecies(icase)%Particles(:,:)  = 0
  enddo

looks like an utter absurd to me. It is a joke that i can not write the universal program with all variables declared with not initially set, but with the arbitrary allocatable dimensions and during specific run assign to that dimensions exact numbers and continue run - this is how all programs should be obviously written. These errors above from the same 'prohibited this, prohibited that' source.

27 Sep 2024 8:13 #31571

Dan,

I can't see what you are doing wrong. I use this approach with both FTN95 and Gfortran. I also have 'ispecies' as an allocatable derived type structure.

What compiler options are you using ?

I am using ftn95 9.04.0.0 with Checkmate x64 /implicit_none etc and this compiles and runs ?

type lostPart
  real*4, allocatable :: Particles(:,:)
end type lostPart

Type (lostPart) ispecies(0:4)
integer :: icase

  do icase=0,4
    allocate (ispecies(icase)%Particles(12,10:20) )
  end do
  write (*,*) 'particles allocated'
  do icase=0,2
    ispecies(icase)%Particles(:,:)  = 0
  enddo
  write (*,*) 'particles initialised'
end

I have used this derived type approach for years and is very useful as an in-memory database , where I have shifted data from disk to memory. This works very well, although I mainly use it to store data, rather than arrays for intensive calculations.

I would enhance your 'type lostPart' to include info such as

  • the record has been allocated
  • the record has been defined
  • the size of allocatable components ( which can vary between records)

My derived type code example is

      TYPE elem_array_record                   ! set in elcomp
         integer*4              :: nd,ns,ilg
         integer*4, allocatable :: lm(:)       ! (nd)      element equation map
         real*8,    allocatable :: sd(:)       ! S(nd,nd) !symmetric stiffness matrix  sd( nt )
         real*8,    allocatable :: xm(:)       ! (nd)      element mass matrix
         real*8,    allocatable :: st(:,:)     ! (ns,nd)   element stress matrix
         real*8,    allocatable :: P(:,:)      ! (nd,ilg)  element load group matrix
         real*8,    allocatable :: tt(:,:)     ! (ns,ilg)  element stress correction matrix
      END TYPE elem_array_record

 type (elem_array_record), allocatable :: elem_array_records(:)        ! (max_elem_records)
...
         allocate ( elem_array_records(max_elem_records), stat=stat )
...
         allocate ( elem_array_records(kel)%st(ns,nd) )
27 Sep 2024 8:36 #31572

enhanced test also works in Plato

 type lostPart
  integer*4 :: is
  real*4, allocatable :: Particles(:,:)
 end type lostPart

 Type (lostPart), allocatable :: ispecies(:)
 integer :: icase, m

  Allocate ( ispecies(0:4) )
  ispecies%is = -1
  write (*,*) 'ispecies allocated'

  do icase=0,4
    m = 12+icase
    allocate (ispecies(icase)%Particles(m,10:20) )
    ispecies(icase)%is = size (ispecies(icase)%Particles)
  end do
  write (*,*) 'particles allocated'

  do icase=0,4
    ispecies(icase)%Particles(:,:)  = 0
    write (*,*) icase, ispecies(icase)%is, maxval (ispecies(icase)%Particles)
  end do
  write (*,*) 'particles initialised'

end
28 Sep 2024 9:41 #31576

I have had a look at this code and FTN95 appears to be conforming to the Standard in this case.

Please login to reply.