Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
告知
Important Update: Community Platform Migration​. Learn more​>

type of array

Carsten_A_
ビギナー
2,785件の閲覧回数
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 件の賞賛
9 返答(返信)
jimdempseyatthecove
名誉コントリビューター III
2,785件の閲覧回数

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

Johannes_Rieke
新規コントリビューター III
2,785件の閲覧回数

[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

 

Carsten_A_
ビギナー
2,785件の閲覧回数

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).

 

Johannes_Rieke
新規コントリビューター III
2,785件の閲覧回数

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?

Carsten_A_
ビギナー
2,785件の閲覧回数

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.

 

Johannes_Rieke
新規コントリビューター III
2,785件の閲覧回数

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

jimdempseyatthecove
名誉コントリビューター III
2,785件の閲覧回数

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

Carsten_A_
ビギナー
2,785件の閲覧回数

Thank you both for your effort to help me!

With Johannes second code it works!

JKKR
ビギナー
2,785件の閲覧回数

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

返信