Allocatable Array
Modules A packaging method for data and subprograms. Syntax of the form: A packaging method for data and subprograms. Syntax of the form: module name_of_module data/type declarations contains subroutines and functions acting on data end module
There are four types of program unit in Fortran: There are four types of program unit in Fortran: Main program - should start with a main PROGRAM statement. Main program - should start with a main PROGRAM statement. External procedures (subprograms) - start with SUBROUTINE or FUNCTION statement. External procedures (subprograms) - start with SUBROUTINE or FUNCTION statement. Block data subprograms (now superseded along with common blocks) - starts with BLOCK DATA statement. Block data subprograms (now superseded along with common blocks) - starts with BLOCK DATA statement. Module - starts with MODULE statement. Module - starts with MODULE statement.
The module may contain any combination of: The module may contain any combination of: definitions of constants definitions of constants definitions of derived types (data structures) definitions of derived types (data structures) data storage declarations data storage declarations procedures (subroutines and functions) procedures (subroutines and functions)
1. Example defining constants MODULE trig_consts IMPLICIT NONE DOUBLE PRECISION, PARAMETER :: pi = d0, & rtod = 180.0d0/pi, dtor = pi/180.0d0 END MODULE trig_consts PROGRAM calculate USE trig_consts IMPLICIT NONE WRITE(*,*) SIN(30.0*dtor) END PROGRAM calculate
2. Module Procedures The general structure of a module: The general structure of a module: starts with a data section starts with a data section then has a CONTAINS statement (if any procedures follow) then has a CONTAINS statement (if any procedures follow) any number of module procedures follow any number of module procedures follow
program main program main use name_of_module use name_of_module end program module grid_module implicit none type param_type integer :: iter ! number of iterations real :: precision ! precision required end type type node_type real :: x ! 1d example, easy to extend to 2d real :: u, residual end type
The module may contain any combination of: The module may contain any combination of: definitions of constants definitions of constants definitions of derived types (data structures) definitions of derived types (data structures) data storage declarations data storage declarations procedures (subroutines and functions) procedures (subroutines and functions)
2. Module Procedures The general structure of a module: The general structure of a module: starts with a data section starts with a data section then has a CONTAINS statement (if any procedures follow) then has a CONTAINS statement (if any procedures follow) any number of module procedures follow any number of module procedures follow
Dynamic Storage There are three forms of dynamic array: automatic, allocatable, and pointer array. There are three forms of dynamic array: automatic, allocatable, and pointer array. 1. Automatic Arrays An automatic array is a local array in a procedure which has its size set when the procedure is called: An automatic array is a local array in a procedure which has its size set when the procedure is called: SUBROUTINE smooth(npts, spectrum) IMPLICIT NONE INTEGER, INTENT(IN) :: npts REAL, INTENT(INOUT) :: spectrum REAL :: space(npts), bigger(2*npts) ! automatic arrays
2. Allocatable Arrays Allocatable arrays are more generally useful as their size may be set at any point. Only the rank has to be declared in advance, with a colon marking the each dimension: Allocatable arrays are more generally useful as their size may be set at any point. Only the rank has to be declared in advance, with a colon marking the each dimension: REAL, ALLOCATABLE :: vector(:), matrix(:,:), three_d(:,:,:) REAL, ALLOCATABLE :: vector(:), matrix(:,:), three_d(:,:,:)
Array size allocation เป็นเทคนิคหนึ่งที่ช่วยให้โปรแกรมทำงานได้ อย่างมีประสิทธิภาพ จากที่ทราบกันว่า การใช้ ตัวแปรอาเรย์นั้น ต้องมีการระบุขนาดมิติที่ แน่นอนในส่วนประกาศก่อน จึงจะสามารถใช้ งานได้ สมมติว่าประกาศใช้ตัวแปรอาเรย์ขนาด มิติ 50x3 แต่ในการใช้งานตัวแปรนั้นจริงๆใช้แค่ เพียง 10x3 ทำให้เกิดพื้นที่เหลือที่ไม่สามารถ ใช้ประโยชน์ใดได้เลย แต่ถ้าเราใช้การ allocate แล้ว เราไม่ต้องระบุขนาดมิติอาเรย์ในส่วน ประกาศ แต่จะให้เรากำหนดด้วยตัวเองในส่วน ดำเนินการของโปรแกรมตามความเหมะสมที่เรา จะใช้งานจริงๆ เป็นเทคนิคหนึ่งที่ช่วยให้โปรแกรมทำงานได้ อย่างมีประสิทธิภาพ จากที่ทราบกันว่า การใช้ ตัวแปรอาเรย์นั้น ต้องมีการระบุขนาดมิติที่ แน่นอนในส่วนประกาศก่อน จึงจะสามารถใช้ งานได้ สมมติว่าประกาศใช้ตัวแปรอาเรย์ขนาด มิติ 50x3 แต่ในการใช้งานตัวแปรนั้นจริงๆใช้แค่ เพียง 10x3 ทำให้เกิดพื้นที่เหลือที่ไม่สามารถ ใช้ประโยชน์ใดได้เลย แต่ถ้าเราใช้การ allocate แล้ว เราไม่ต้องระบุขนาดมิติอาเรย์ในส่วน ประกาศ แต่จะให้เรากำหนดด้วยตัวเองในส่วน ดำเนินการของโปรแกรมตามความเหมะสมที่เรา จะใช้งานจริงๆ
การ allocate นั้นจะทำการเขียนคำสั่งที่ส่วนประกาศ ดังนี้ การ allocate นั้นจะทำการเขียนคำสั่งที่ส่วนประกาศ ดังนี้ รูปแบบ ชนิดตัวแปร, ALLOCATABLE, DIMENSION(:[, :,...] ) :: ชื่อตัวแแปร หรือ หรือ ชนิดตัวแปร, ALLOCATABLE :: ชื่อตัวแปร (:[, :,...] ) และทำการเขียนคำสั่งที่ส่วนดำเนินการดังนี้ และทำการเขียนคำสั่งที่ส่วนดำเนินการดังนี้ รูปแบบ ALLOCATE ( ตัวแปรอาเรย์ ( ขนาด มิติ ),STAT= ตัวแปรจำนวนเต็ม ) สมมติว่า เราต้องการกำหนดให้ อาเรย์ yy ซึ่งมีชนิด เป็นจำนวนจริง ให้มีมิติเป็น 3 คูณ 3 สามารถทำได้ ดังนี้ สมมติว่า เราต้องการกำหนดให้ อาเรย์ yy ซึ่งมีชนิด เป็นจำนวนจริง ให้มีมิติเป็น 3 คูณ 3 สามารถทำได้ ดังนี้
REAL, ALLOCATABLE, DIMENSION( :, : ) :: yy INTEGER di,status PRINT *,'enter a dimension of array[eg. 5,4] : ' ! ใส่ค่า 3,3 ALLOCATE ( yy(di,di),STAT=status) ตัวแปรจำนวนเต็มของ STAT นั้น จะเก็บข้อมูลว่า สามารถที่จะทำการ allocate ได้หรือไม่ ถ้าตัวแปร ดังกล่าวมีค่าเท่ากับ 0 แสดงว่าทำการ allocate สำเร็จแต่ถ้าตัวแปรมีค่าเป็นจำนวนบวก แสดงว่า ทำการ alloocate ไม่สำเร็จ ตัวแปรจำนวนเต็มของ STAT นั้น จะเก็บข้อมูลว่า สามารถที่จะทำการ allocate ได้หรือไม่ ถ้าตัวแปร ดังกล่าวมีค่าเท่ากับ 0 แสดงว่าทำการ allocate สำเร็จแต่ถ้าตัวแปรมีค่าเป็นจำนวนบวก แสดงว่า ทำการ alloocate ไม่สำเร็จ
เราสามารถที่จะยกเลิกการทำ allocate ได้ โดยเขียนคำสั่งที่ส่วนดำเนินการดังนี้ เราสามารถที่จะยกเลิกการทำ allocate ได้ โดยเขียนคำสั่งที่ส่วนดำเนินการดังนี้ รูปแบบ DEALLOCATE ( ตัวแปรอาเรย์,STAT= ตัวแปรจำนวนเต็ม ) หลักการพิจารณาก็ใช้แบบเดียวกับกรณีของ allocate ครับ หลักการพิจารณาก็ใช้แบบเดียวกับกรณีของ allocate ครับ
PROGRAM test_array_allocation IMPLICIT NONE INTEGER,ALLOCATABLE,DIMENSION( :, :) :: show INTEGER :: i,j,status,m,n REAL,ALLOCATABLE :: hide( :, : ) PRINT *,'enter two number[eg. 1,1]: ' ! ใส่ค่า 3,2 READ (*,*) i,j ALLOCATE (show(i,j),hide(j,i),STAT=status) show=1hide=10.0 DO m=1,i,1 DO n=1,j,1 PRINT 31,'value in show ',m,':',n,'=',show(m,n) END DO DO m=1,j,1 DO n=1,i,1 DO n=1,i,1 PRINT 33,'value in hide ',m,':',n,'=',hide(m,n) END DO 31 FORMAT (' ',X,A,I2,A,I2,A,I4) 33 FORMAT (' ',X,A,I2,A,I2,A,F5.2) END PROGRAM
จากตัวอย่างด้านบนได้ผล ลัพธ์ดังนี้ จากตัวอย่างด้านบนได้ผล ลัพธ์ดังนี้ enter two number[eg. 1,1]: 2,1 value in show 1: 1= 1 value in show 2: 1= 1 value in hide 1: 1=10.00 value in hide 1: 2=10.00
3. Pointer arrays An allocatable array cannot be passed to a procedure when in an un-allocated state. An allocatable array cannot be passed to a procedure when in an un-allocated state. But this can be done with a pointer array: But this can be done with a pointer array:
REAL, ALLOCATABLE, DIMENSION( :, : ) :: yy INTEGER di,status PRINT *,'enter a dimension of array[eg. 5,4] : ' ! ใส่ค่า 3,3 ALLOCATE ( yy(di,di),STAT=status) ตัวแปรจำนวนเต็มของ STAT นั้น จะเก็บข้อมูลว่า สามารถที่จะทำการ allocate ได้หรือไม่ ถ้าตัวแปร ดังกล่าวมีค่าเท่ากับ 0 แสดงว่าทำการ allocate สำเร็จแต่ถ้าตัวแปรมีค่าเป็นจำนวนบวก แสดงว่า ทำการ alloocate ไม่สำเร็จ ตัวแปรจำนวนเต็มของ STAT นั้น จะเก็บข้อมูลว่า สามารถที่จะทำการ allocate ได้หรือไม่ ถ้าตัวแปร ดังกล่าวมีค่าเท่ากับ 0 แสดงว่าทำการ allocate สำเร็จแต่ถ้าตัวแปรมีค่าเป็นจำนวนบวก แสดงว่า ทำการ alloocate ไม่สำเร็จ
3. Pointer arrays An allocatable array cannot be passed to a procedure when in an un-allocated state. An allocatable array cannot be passed to a procedure when in an un-allocated state. But this can be done with a pointer array: But this can be done with a pointer array:
PROGRAM pdemo IMPLICIT NONE REAL, POINTER :: parray(:) OPEN(UNIT=9, FILE='mydata', STATUS='old') CALL readin(9, parray) WRITE(*,*)'array of ', SIZE(parray), ' points:' WRITE(*,*) parray DEALLOCATE(parray)CONTAINS SUBROUTINE readin(iounit, z) INTEGER, INTENT(IN) :: iounit REAL, POINTER :: z(:) ! cannot use INTENT for pointer INTEGER :: npoints READ(iounit) npoints ! find how many points to read ALLOCATE(z(1:npoints)) ! allocate the space READ(iounit) z ! read the entire array END SUBROUTINE readin END PROGRAM pdemo