Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

type of array

Carsten_A_
Beginner
1,555 Views
I would like to solve following task:
I have got a grid (nCellsY, nCellsZ). Each grid cell can contain no fiber, one fiber ore more fibers.
I know in which cell the fibers are. 

I need to know the indices of the fibers which are in one cell. 
For example a short list of fibers:

fiberInCellY = (/1,5,3,5,4,3,1/)
fiberInCellZ = (/1,4,6,1,2,5,1/)

I would like to get following:

Cell              Index of fiber      Index of fiber
GridFibers(1,1)   1                   7
GridFibers(5,1)   4
GridFibers(4,2)   5
GridFibers(5,4)   2

...and so on...

but with my following code it shows me no index:

PROGRAM run
IMPLICIT NONE
INTEGER, DIMENSION(7) :: fiberInCellY, fiberInCellZ
INTEGER i, j, k, nCellsY, nCellsZ


type :: indFibInCell
    integer, allocatable, dimension(:) :: ind
end type indFibInCell

type (indFibInCell), allocatable, dimension(:,:) :: Gridfibers

fiberInCellY = (/1,5,3,5,4,3,1/)
fiberInCellZ = (/1,4,6,1,2,5,1/)
nCellsY = 6
nCellsZ = 6

allocate(GridFibers(nCellsY,nCellsZ))

do j=1, nCellsZ
    do i=1, nCellsY
        do k=1, 7
            if (i == fiberInCellY(k) .and. j == fiberInCellZ(k)) then
                Gridfibers(i,j)%ind = k
                print *, "Gridfibers(",i, "," ,j, ")", Gridfibers(i,j)%ind
            end if
        end do
    end do  
end do

END PROGRAM run

 

0 Kudos
9 Replies
jimdempseyatthecove
Honored Contributor III
1,555 Views

Your indFibInCell has ind as allocatable

1) You did not allocate it (them in Gridfibers)

2) Your code does not indicate that it expects it to be allocated

Jim Dempsey

0 Kudos
Johannes_Rieke
New Contributor III
1,555 Views

[fortran]

PROGRAM run
IMPLICIT NONE
INTEGER, DIMENSION(7) :: fiberInCellY, fiberInCellZ
INTEGER i, j, k, l, nCellsY, nCellsZ, guess
 
 
type :: indFibInCell
    integer, allocatable, dimension(:) :: ind
end type indFibInCell
 
type (indFibInCell), allocatable, dimension(:,:) :: Gridfibers
 
fiberInCellY = (/1,5,3,5,4,3,1/)
fiberInCellZ = (/1,4,6,1,2,5,1/)
nCellsY = 6
nCellsZ = 6
 
allocate(GridFibers(nCellsY,nCellsZ))
guess=10
do j=1, nCellsZ
    do i=1, nCellsY
        allocate(Gridfibers(i,j)%ind(guess))
        l = 0
        do k=1, 7
            if (i == fiberInCellY(k) .and. j == fiberInCellZ(k)) then
                l = l + 1
                Gridfibers(i,j)%ind(l) = k
            end if
        end do
        if (l.gt.0) print *, "Gridfibers(",i, "," ,j, ")", Gridfibers(i,j)%ind(1:l)
    end do
end do
 
END PROGRAM run

[/fortran]

output

Gridfibers( 1 , 1 ) 1 7
Gridfibers( 5 , 1 ) 4
Gridfibers( 4 , 2 ) 5
Gridfibers( 5 , 4 ) 2
Gridfibers( 3 , 5 ) 6
Gridfibers( 3 , 6 ) 3

Try this modification. As Jim says, you have not allocated %ind. With F2003 semantics on %ind can be reallocated if it necessary.

By the way. Couldn't this kind of coding 'error' (not allocated element of a type) seen by the compiler at compile time? Missed I something?

Regards,

Johannes

 

0 Kudos
Carsten_A_
Beginner
1,555 Views

Thank you Jim for you reply,

that is exactly the problem I have. I would like to get a "dynamik ind array". If 3 fibers are in a cell, "ind" should have a length of 3. If a cell contains no fiber, "ind" should have a length of 1 (filled with 0).

 

0 Kudos
Johannes_Rieke
New Contributor III
1,555 Views

Hi Carsten,

that is excatly what you get if you set guess=1 and use F2003 sementics on. You should initialize Gridfibers(i,j)%ind(1)=0 after allocation.Gridfibers(i,j)%ind will have diffent length in the end.

Regards,

Johannes

ps: OFFTOPIC How can I avoid these ugly blank lines with firefox?

0 Kudos
Carsten_A_
Beginner
1,555 Views

Hi Johannes,

thx for your input! The Code you are posted works well. I added the line "Gridfibers(i,j)%ind=0" after allocation.

Does IND always needs a memory of 10 entries by using guess=10?

I do not understand what you mean with F2003 sementics on!? If I change "guess=1" and "Gridfibers(i,j)%ind(1)=0" I get following error of course: IND has value 2 which is greater than the upper bound of 1.

 

0 Kudos
Johannes_Rieke
New Contributor III
1,555 Views

Hi Carsten,

F2003 semantics are a compiler flag, which turns along other things the automatic right hand side (re)allocation on. This could cause curious errors, if you are not code correctly. I assume that many programmers don't want to turn it on by default.

However, in VS goto properties -> Fortran -> languange -> Enable F2003 sematics and set it to Yes /standard-semantics. Or set in the command line /standard-semantics.

Only then you can set guess=1. If your code requires 2 elements in ind, the array is dynamically extended through 'automatic right hand sinde allocation' (e.g. like in Matlab). If you don't use this, your code will fail with array bound exceeds (if check is turned on).

Best regards,

Johannes

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,555 Views

I think you mean reallocate left hand side.

Gridfibers(i,j)%ind(l) = k

The above is a scalar assignment, the F2003 spec says reallocation to shape on right. This would require using

Gridfibers(i,j)%ind(l) = /Gridfibers(i,j)%ind(1:l-1), k/

or something like that to append to the array (if necessary) to apply k into the l'th  and last element.

Jim Dempsey

0 Kudos
Carsten_A_
Beginner
1,555 Views

Thank you both for your effort to help me!

With Johannes second code it works!

0 Kudos
JKKR
Beginner
1,555 Views

Hi Carsten,

nice to hear that it works for you. That the other versions did not work encouraged me to find a solution. Here it is:

[fortran]

PROGRAM run
IMPLICIT NONE
INTEGER, DIMENSION(7) :: fiberInCellY, fiberInCellZ
INTEGER               :: i, j, k, l, nCellsY, nCellsZ, guess
type :: indFibInCell
    integer, allocatable, dimension(:) :: ind
end type indFibInCell
type (indFibInCell), allocatable, dimension(:,:) :: Gridfibers
integer, allocatable :: idummy(:)

fiberInCellY = (/1,5,3,5,4,3,1/)
fiberInCellZ = (/1,4,6,1,2,5,1/)
nCellsY = 6
nCellsZ = 6
allocate(GridFibers(nCellsY,nCellsZ))
guess=1
do j=1, nCellsZ
    do i=1, nCellsY
        allocate(Gridfibers(i,j)%ind(guess))
        l = 0
        do k=1, 7
            if (i == fiberInCellY(k) .and. j == fiberInCellZ(k)) then
                l = l + 1
                ! --- begin working version 1
                ! this is working without /assume realloc_lhs
                !allocate(idummy(l))
                !idummy(1:l-1)=Gridfibers(i,j)%ind(1:l-1)
                !idummy(l)=k
                !call move_alloc(idummy,Gridfibers(i,j)%ind)
                ! --- end working verion 1
                !
                !!Gridfibers(i,j)%ind(1:l) = [Gridfibers(i,j)%ind(1:l-1),k] ! not working
                !!Gridfibers(i,j)%ind(l) = k                                ! also not working  

                ! --- now with /assume realloc_lhs
                Gridfibers(i,j)%ind = [Gridfibers(i,j)%ind(1:l-1),k] ! This should work and does
            end if
        end do
        if (l.gt.0) print *, "Gridfibers(",i, "," ,j, ")", Gridfibers(i,j)%ind(1:l)
    end do
end do
END PROGRAM run

[/fortran]

 

The trick is not to use array sections like (:) or (1:l) but to use the whole sub-array as an object. This says the standard F2003. Nevertheless, I prefer the manual way, because it would be easier to track down mysterious errors.

Best regards,

Johannes

0 Kudos
Reply