5

Đây là một chút phức tạp; Tôi hoan nghênh mọi ý kiến ​​về cách cải thiện sự rõ ràng của câu hỏi.Phân bổ mảng động với kích thước phụ thuộc lẫn nhau

Ok, nói rằng tôi có một mảng:

real, allocatable :: A(:,:,:) 

và tôi muốn phân bổ nó trước khi tôi sử dụng nó. Có thể cho kích thước của chiều thứ ba phụ thuộc vào kích thước của chiều thứ hai không?

Ví dụ:

do i=1,n 
allocate(A(3,i,i**2)) 
end do 

Rõ ràng những điều trên không có tác dụng. Tôi muốn kết thúc với một mảng (hoặc một tập hợp các mảng) với hình dạng (s)

(3,1,1), (3,2,4), (3,3,9), ... (3, n, n^2) 

nơi kích thước của kích thước thứ ba là hình vuông kích thước của chiều thứ hai.

Quy tắc của tôi cho kích thước của thứ nguyên phụ thuộc phức tạp hơn một chút, nhưng nếu có thể tôi có thể làm phần còn lại.

Điều này có khả thi không? Nếu vậy, làm thế nào tôi có thể thực hiện nó ở Fortran?

Điều gì sẽ shape(A) trả lại? Điều đó sẽ rất thú vị.

thay thế khác của tôi là để phân bổ đến kích thước tối đa cần thiết, và cẩn thận để chỉ sử dụng một số yếu tố trong tính toán, tức là

allocate(A(3,n,n**2)) 

Mặc dù tôi không cứng lên vào bộ nhớ tại thời điểm này, tôi muốn thực hành lập trình tốt. Đây là một vấn đề thú vị.

Cảm ơn bạn.

EDIT:

gì về việc có kích thước của một chiều hướng phụ thuộc vào giá trị của một phần tử trong không gian khác?

Trong câu trả lời dưới đây kích thước của mảng trong cả hai kích thước phụ thuộc vào chỉ số của B. Tôi muốn một cái gì đó dọc theo dòng của

type myarray 
    real :: coord(3) 
    integer,allocatable :: lev(:) 
    integer, allocatable :: cell(:) 
endtype myarray 

type(myarray), allocatable :: data 

allocate(data(m)) 
allocate(data%lev(n)) 

forall (j=1:n) !simple now, for argument's sake 
    lev(j)=j 
endforall 

! I was thinking of using a FORALL loop here, but the errors returned 
! suggested that the compiler (gfortran) didn't expect IF blocks and ALLOCATE 
! statements in a FORALL block 
do i=1,m 
    do j=1,n 
     allocate(data(i)%cell(lev(j)**2)) 
    enddo 
enddo 

Bạn nhận được ý tôi chứ? Nhưng chương trình rơi xuống khi nó cố gắng phân bổ các biến đã được phân bổ, ví dụ: khi i=1, nó phân bổ data(1)%cell(1) và sau đó cố gắng phân bổ data(1)%cell(2) ... uh oh. Những gì tôi muốn là một cái gì đó như:

Mỗi data(i) có một mảng lev(j) các giá trị, với j chạy từ 1 đến n, và cho mỗi giá trị lev(j) chúng tôi có một cell kích thước lev^2. Lưu ý rằng những cell là duy nhất cho mỗi data(i) và mỗi lev và kích thước của số đó cell cụ thể phụ thuộc vào giá trị lev tương ứng và có thể tương ứng với data(i).

Tôi có phải sử dụng loại có nguồn gốc trong loại có nguồn gốc không?

+1

Chỉ cần để bạn biết, loại mảng bạn đang tìm kiếm được gọi là mảng "lởm chởm", so với mảng "hình chữ nhật". IRO-bot bên dưới có câu trả lời đúng; trong các mảng Fortran của mình luôn là hình chữ nhật nhưng bạn có thể sử dụng các loại được xác định để tạo cấu trúc của riêng bạn. –

+0

"Bị lởm chởm" ... này, điều đó có ý nghĩa, theo hình ảnh. "... bạn có thể sử dụng các loại được xác định để tạo cấu trúc của riêng bạn." Có thật không? Vì vậy, nếu tôi muốn một mảng có hình dạng tăng cho đến nửa chừng sau đó giảm, hoặc sau chuỗi Fibonacci, hoặc là hoàn toàn ngẫu nhiên - đó là tất cả có thể cho nỗ lực không quá nhiều ... mát mẻ! –

+0

@SamuelTan Tôi tiếp tục chỉnh sửa câu trả lời của mình bằng mã được cập nhật để giải quyết vấn đề mới của bạn. So sánh hai mã để xem bạn đang làm gì sai. – milancurcic

Trả lời

9

Có, bạn có thể sử dụng một loại có nguồn gốc để thực hiện điều này:

TYPE array 
    REAL,DIMENSION(:,:,:),ALLOCATABLE :: A 
ENDTYPE array 

INTEGER :: i 
INTEGER,PARAMETER :: n=10 

TYPE(array),DIMENSION(:),ALLOCATABLE :: B 

ALLOCATE(B(n)) 

DO i=1,n 
    ALLOCATE(B(i)%A(3,i,i*i)) 
    WRITE(*,*)SHAPE(B(i)%A) 
ENDDO 

END 

Cách tiếp cận này cho phép mỗi phần tử của mảng B là một mảng đa chiều của một hình dạng khác nhau.

Đầu ra của chương trình là như mong đợi:

 3   1   1 
     3   2   4 
     3   3   9 
     3   4   16 
     3   5   25 
     3   6   36 
     3   7   49 
     3   8   64 
     3   9   81 
     3   10   100 

EDIT: Để trả lời câu hỏi tiếp tục chỉnh sửa OP của. Vâng, nó có vẻ như bạn sẽ cần phải làm một cái gì đó như thế này, sử dụng lồng loại có nguồn gốc (so sánh với ví dụ mã của bạn để tìm ra những gì bạn đã làm sai):

integer,parameter :: m=3,n=5 

type cellarray 
    integer,dimension(:),allocatable :: c 
endtype cellarray 

type myarray 
    integer,allocatable :: lev(:) 
    type(cellarray),dimension(:),allocatable :: cell 
endtype myarray 

type(myarray),dimension(:),allocatable :: B 

allocate(B(m)) 

! Allocate and assign lev and cell: 
do i=1,m 
    allocate(B(i)%lev(n)) 
    allocate(B(i)%cell(n)) 
    do j=1,n 
    B(i)%lev(j)=j 
    enddo 
enddo 

! Based on value of lev, allocate B%cell%c:  
do i=1,m 
    do j=1,n 
    allocate(B(i)%cell(j)%c(B(i)%lev(j)**2)) 
    enddo 
enddo 

! Print out to check that it works: 
do j=1,n 
    write(*,*)j,B(1)%lev(j),SIZE(B(1)%cell(j)%c) 
enddo 

end 

Cố gắng này với gfortran 4.6.2. Nó tạo ra sản lượng dự kiến:

 1   1   1 
     2   2   4 
     3   3   9 
     4   4   16 
     5   5   25 
+5

Nó hoạt động với bất kỳ gfortran gần đây tôi đã gặp phải (4.1.2 là hoàn toàn lỗi thời). –

+0

@VladimirF Cảm ơn nhận xét - Tôi đã chỉnh sửa câu trả lời của mình. Tôi đã không nhận thức được điều này kể từ khi tôi hầu như không bao giờ sử dụng gfortran, và đây là những gì chúng tôi có trên cụm máy tính của chúng tôi. Tôi cho rằng sysadmin của chúng tôi không bận tâm cập nhật nó. :) – milancurcic

+0

Đó là một sự an ủi. Tôi sử dụng gfortran, và tôi sợ tôi có thể phải có trình biên dịch khác. –

1

Tôi nghĩ bạn có thể làm điều này chỉ đơn giản bằng cách phân bổ/deallocating mảng

Program test 
    Implicit none 
    Real, dimension(:,:,:), allocatable :: A 
    Integer :: i,N 
    Write(*,*)"Enter N"; Read(*,*)N 
    Do i = 1, N 
    if(Allocated(A)) then 
    deallocate(A);Allocate(A(i,i,i*i)) 
    else 
    allocate(A(i,i,i*i)) 
    end if 
    Write(*,*)Shape(A) 
    End do 
end program test 

Biên soạn chương trình dụng gfortran cho:

Enter N 
5 
      1   1   1 
      2   2   4 
      3   3   9 
      4   4   16 
      5   5   25 
+0

Tôi không chắc chắn, nhưng tôi nghĩ bạn có thể đã bỏ lỡ điểm của câu hỏi.Câu hỏi dường như hỏi về các mảng không phải là hình chữ nhật/răng cưa và người hỏi đã đề cập ý tưởng về việc có hình chữ nhật siêu lớn nhất và chỉ sử dụng (cẩn thận) những yếu tố mong muốn đó. – francescalus

+0

Tôi nghĩ đây là câu trả lời cho câu hỏi này {Có thể cho kích thước của chiều thứ ba phụ thuộc vào kích thước của chiều không gian thứ hai không? } – Navaro

+0

* Có thể cho kích thước của chiều thứ ba phụ thuộc vào kích thước của chiều thứ hai không? * Vậy có hay không? Tôi không thể nhìn thấy câu trả lời cho câu trả lời này. –

Các vấn đề liên quan