lab5 |
PARAMETER STATEMENT, EXPLICIT INTERFACE, MODULES AND THE IDB DEBUGGER |
||||||||||||||||||||
NOTE: for all lab and projects create the proper directories and subdirectories !!!REMINDER FOR THOSE WHO ARE NOT LISTENINGAll
projects in aero 361 need
to follow a strict layout. The purpose of the layout is to organize the
work and mitigate clutter when the projects become big --- specially
when reports are involved. The reports will be written in LaTex which
is basically writing code! The projects will also emphasize post
processing from using Matlab, Tecplot and Xmgrace. Thus a single
project will consist of source codes in f90, latex source codes, data
from the f90 code and tecplot or matlab figures. All these various
items will have to be placed in separate directories so that clutter
and confusion is minimized and efficiency is maximized: your first
lesson in OPTIMIZATION. The figure below illustrates the directory
structure for proj[#] or lab[#]. All other projects will follow the
same procedure
and layout.
/home/joeusr
![]() aero361/ ![]() labs ![]() lab5 ![]() ![]() src/ dat/ bin/ report/ PARAMETER STATEMENTWhen dynamic allocation was not available in f77 a named variable constant had to be initialized in order allocate space for arrays. The extent of the arrays was fixed by this named variable constant. The program could allocate arrays up to and less than that set by the named variable constant. A named variable constant in short is a PARAMETER, where its value cannot be changed. It can be a real or an integer
PROGRAM WITH PARAMETER STATEMENTS TO DEFINE ARRAY BOUNDSWrite the code below and call it main_param.f90 and run the code. Then edit the code such that
program main implicit none PROGRAM WITH ALLOCATBLE STATEMENTS TO DEFINE ARRAY BOUNDSWrite the code shown in this section below and name it main_allc.f90. Make sure there is an input.dat file in the iof directory from which the dimensions of the arrays can be read in. Of course, you will have to create one! Compile and run the code with small dimensions (n=10, m=10, l=10) and then try the big one as you did in the above exercise. When arrays are set as allocatable the compiler will not catch it, as with the Parameter statement, the problem will be noticed on run time or when the code is executed. When arrays are designated as allocatable they can be created and destroyed while the code is executing.program main PASSING ARRAYS THROUGH THE ARGUMENT LISTCommon mistakes occur when arrays and variables are passed or accessed through the argument list. The errors are due to address errors because the dummy arrays and variables were not assigned the correct address'. When compiling the codes one must use the -C flag to check where these types of errors occur and then correct them. In the example below Asub calls Bsub. The arrays are explicitly shaped in Asub and then addressed in Bsub as explicit dummy shaped arrays. The names of the arrays do not have to be the same what must be adhered is
Explicitly Shaped ArrayWhen the bounds of the array is set by the parameter statement the extent of the array is fixed. If the bounds are exceeded and address error will occurExplicitly Shaped dummy ArrayWhen the bounds of the array are set by the calling program as shown in subroutine Bsub. The arrays in Bsub have their leading dimension and extent set by the integers: ismax and jsmax.
Automatic ArraysWhen arrays are set as allocatable. The extent of the arrays are set at run time. The program can allocate and deallocate arrays while the program is running. However the allocation and deallocation step is an operation and therefore depending on the size of the arrays they can be cpu intensive. The approach to allocation/deallocation should not be reckless!When arrays are allocated in a subroutine and they are local to the subroutine only then when the program exits the subroutine the arrays are destroyed automatically. If the same arrays are required in other routines then
MODULESIn the past (f77) the
most common way for procedures to have access to data types was through
the common block. The common block could be confined to a file that a
procedure would include to access the data types. Items included in the
common block were commonly referred to as globals. The same method of
using globals is used in C which include the global.h file in a
procedure.
However all this changed for the better in f90. In f90 the common block was replaced by a powerful subset of the procedure family called Modules. The Modules could be compared to a Class in C++. Procedures like Subroutines and Functions can be included in a Module. This type of interface is called an explicit interface as shown in the next section. To use Modules as a repository of global elements that other procedures can access without having to write messy argument lists is simple and straight forward. When accessing or using modules the module source file should always be compiled before its dependencies. Suppose you have three files that access contents in global.f90, where global.f90 is a module file. To compile the program the global.f90 file is compiled 1st and then followed by the others. To compile the above test case (be sure to have directory /lab5/global with src/ bin/
CONTAINS STATEMENTAn internal procedure is a procedure contained inside some host program or procedure. A main program may contain an internal function or subroutine. An external procedure may also contain one or many internal procedures. Internal procedures can only be invoked by their host programs. Anything declared in the host program is accessable by the internal programs: no need to use the argument list.EXPLICIT INTERFACECreate a directory called lab5/decomp/ and in it create the src/, bin/ and dat/ directories. Download the source files into the src/ directory only. You will be required to perform various tasks to further understand the concepts in programming. By now you should know how to compile, link and execute the program.Explicit
Interface
The official Linear Solver routine for this class is decomp.f90: this
routines has been tested in Gams and contains two procedures (decomp
and solve). There is a driver.f90
program that calls decomp and solve. The decomp and solve
procedures are in a Module
creating
an Explicit interface. You
are not to modify or add anything into the
routines! The contents of the code within each routine must be
untouched. You are only to add the Module Interface as shown below. |
| Original and Correct
Form |
Incorrect Form to
test the compiler |
CALL DECOMP(NDIM,N,COND,IPVT,WORK,A) |
CALL DECOMP(NDIM,N,COND,IPVT,WORK) |
Module Linear_solver
contains
SUBROUTINE DECOMP(NDIM,N,COND,IPVT,WORK,A)
IMPLICIT NONE
INTEGER :: NDIM,N
! | Assumed Shape dummy array:
! | If the routine is in a module creating an explicit interface then one can use
! | assumed shape dummy array specifications for the arrays in the argument list.
! | The extent and leading dimensions of the arrays in the argument list are defined
! | by the calling program.
! | Note this can only be used if the routine is in module like this one.
! REAL(KIND=8) :: WORK(:),A(:,:) ! assumed shape dummy arrays
! | Explicit shape dummy Arrays:
! | Commonly used method in passing arrays through argument lists. In this method the extent or size of
! | rows and columns of the arrays need to passed through the argument list. This method is commonly
! | used where as the above method is for more advanced users.
REAL(KIND=8) :: WORK(1:NDIM),A(1:NDIM,1:NDIM)
REAL(KIND=8) :: ANORM,T,EK,YNORM,ZNORM,COND
idb startup file for download: save this in your $HOME as .idbrc |
| main.f90 |
| input.f90 |
| solver.f90 |
| output.f90 |
| global.f90 |
| input.dat |
| <bash> ifc -c -w -g global.f90 main.f90 solver.f90 output.f90 input.f90 |
| <bash> ifc -g global.o main.o solver.o output.o input.o -o ../bin/code.x |
| NOTE: You
should now be in the bin/ dir |
| <bash>
idb code.x |
| <bash>
idb-e code.x |
| <bash>
idb -gui code.x or idb-e -gui code.x |
step1Invoke the debugger using the command shown below
When the debugger loads the executable the following lines will show up on the shell
step2: list
line# line#
The first step after loading a executable is to list the contents of
the main program from line 1 down to the next 50 lines. |
| weaponX:>l
1 |
| weaponX:>l
1 1 program main ! All programs have to have a main program header 2 3 Use global 4 implicit none ! All procedures have to have a implicit none command 5 integer :: ismax,jsmax,ksmax 6 integer :: io_write 7 integer :: status 8 9 10 call input(ismax,jsmax,ksmax,io_write) 11 12 ! | Allocation step :: 13 14 allocate(x(1:ismax,1:jsmax,1:ksmax), stat=status) 15 if(status /= 0) write(6,*) "deallocation failed at line 13" 16 allocate(y(1:ismax,1:jsmax,1:ksmax), stat=status) 17 if(status /= 0) write(6,*) "deallocation failed at line 16" 18 allocate(z(1:ismax,1:jsmax,1:ksmax), stat=status) 19 if(status /= 0) write(6,*) "deallocation failed at line 19" 20 allocate(w(1:ismax,1:jsmax,1:ksmax), stat=status) 21 if(status /= 0) write(6,*) "deallocation failed at line 21" 22 23 call solver(ismax,jsmax,ksmax) 24 call output(ismax,jsmax,ksmax,io_write) 25 26 ! | Deallocation step :: 27 28 deallocate(x, stat=status) 29 if(status /= 0) write(6,*) "deallocation failed at line 14" 30 deallocate(y, stat=status) 31 if(status /= 0) write(6,*) "deallocation failed at line 18" 32 deallocate(z, stat=status) 33 if(status /= 0) write(6,*) "deallocation failed at line 20" 34 deallocate(w, stat=status) 35 if(status /= 0) write(6,*) "deallocation failed at line 22" 36 37 38 39 end program main weaponX:> |
| idb:>b
10 [#1: stop at "main.f90":10 ] weaponX:>b 20 [#2: stop at "main.f90":20 ] |
| idb:>status #1 PC==0x8049a9f in subroutine main() "main.f90":10 { break } #2 PC==0x8049f27 in subroutine main() "main.f90":20 { break } |
| <idb>delete 1 <idb>delete 2 |
| <idb>delete all |
| idb:>b
10 [#1: stop at "main.f90":10 ] weaponX:>b 20 [#2: stop at "main.f90":20 ] |
| [1] stopped at [subroutine main():10
0x8049a9f] 10 call input(ismax,jsmax,ksmax,io_write) |
| weaponX:>sh
clear weaponX:> l 1 |
| weaponX:>
l 3 10 |
| weaponX:>l
1 1 program main ! All programs have to have a main program header 2 3 Use global 4 implicit none ! All procedures have to have a implicit none command 5 integer :: ismax,jsmax,ksmax 6 integer :: io_write 7 integer :: status 8 9 > 10 call input(ismax,jsmax,ksmax,io_write) 11 12 ! | Allocation step :: 13 14 allocate(x(1:ismax,1:jsmax,1:ksmax), stat=status) 15 if(status /= 0) write(6,*) "deallocation failed at line 13" 16 allocate(y(1:ismax,1:jsmax,1:ksmax), stat=status) 17 if(status /= 0) write(6,*) "deallocation failed at line 16" 18 allocate(z(1:ismax,1:jsmax,1:ksmax), stat=status) 19 if(status /= 0) write(6,*) "deallocation failed at line 19" 20 allocate(w(1:ismax,1:jsmax,1:ksmax), stat=status) 21 if(status /= 0) write(6,*) "deallocation failed at line 21" 22 23 call solver(ismax,jsmax,ksmax) 24 call output(ismax,jsmax,ksmax,io_write) 25 26 ! | Deallocation step :: 27 28 deallocate(x, stat=status) 29 if(status /= 0) write(6,*) "deallocation failed at line 14" 30 deallocate(y, stat=status) 31 if(status /= 0) write(6,*) "deallocation failed at line 18" 32 deallocate(z, stat=status) 33 if(status /= 0) write(6,*) "deallocation failed at line 20" 34 deallocate(w, stat=status) 35 if(status /= 0) write(6,*) "deallocation failed at line 22" 36 37 38 39 end program main |
| weaponX:>
w |
| <idb>s <idb>l 1 |
| weaponX:>l
1 1 Subroutine input(ismax,jsmax,ksmax,io_write) 2 use global ! Module global that contains the type of 3 ! x, y and z variables and arrays 4 implicit none 5 6 integer :: io_read ! open stetement assignment number: input 7 integer :: io_write ! open stetement assignment number: output 8 9 integer :: ismax 10 integer :: jsmax 11 integer :: ksmax 12 > 13 io_read = 101 ! assigning the unit number 101 to integer 14 ! variable io_read 15 io_write= 102 ! assigning the unit number 102 to integer 16 ! variable io_write 17 18 open(unit=io_read, file="../bin/input.dat",status="Old") 19 20 read(io_read,*) ismax ! max counter in i 21 read(io_read,*) jsmax ! max counter in j 22 read(io_read,*) ksmax ! max counter in k 23 24 read(io_read,*) xl ! x lower bound 25 read(io_read,*) xu ! x upper bound 26 27 read(io_read,*) yl ! y lower bound 28 read(io_read,*) yu ! y upper bound 29 30 read(io_read,*) zl ! z lower bound 31 read(io_read,*) zu ! z upper bound 32 33 34 end subroutine input |
| <idb>p io_read |
| <idb>b 34 <idb>c |
| <idb>p ismax <idb>p jsmax : : |
| <idb>c to 34 |
| <idb>continue to 34 |
| <idb> stop in output <idb> c |
| <idb> bp output <idb> c |
| <idb>b 30 <idb>c <idb>sh clear <idb>l 1 |
| <idb>p x <idb>p y(2,3,4) <idb>p w(1,2,:) |
| <idb>whatis x <idb>whatis jsmax |
| <idb>q |
| <idb>stop at "line number" if(i==2 .and. j==4
.and. k==7) |
| <idb>when at "line number" if(i==2 .and. j==4
.and. k==7) {p "variable" or "array"} |
| <idb>record input {filename} |
| <idb>playback {filename} |
| set
$listwindow=53 set $prompt = "weaponX:>" alias ss "s;w" alias w " list $curline - 5:40" alias pi "playback input" alias cle " sh clear" |