- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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
コピーされたリンク
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
[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
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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).
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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?
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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.
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
Thank you both for your effort to help me!
With Johannes second code it works!
- 新着としてマーク
- ブックマーク
- 購読
- ミュート
- RSS フィードを購読する
- ハイライト
- 印刷
- 不適切なコンテンツを報告
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