A short guide to using MinGW for Fortran programming on PCs
Ron Ghosh, ILL, October 2004
Programming in Fortran is not hard, and the very simple examples given here are easily adaptable to be really useful programs. They introduce the reader to a few libraries which are available at the ILL which offer useful graphics on PC-Windows. The MinGW program suite includes g77 (aka f77) C, C++, objective C, from the GNU package. The self extracting file MinGW-3.1.0-1.exe contains the compilers and tools (about 45MB).
Equivalent libraries exist also for CYGWIN and for Macintosh OS-X all using the same basic GNU tools.
A very simple Fortran program to read and write out a data file
Program progrw.f - written with Notepad
program progrw c***** a simple program to read and write data c R. Ghosh, ILL, version 1 October 2004 c g77 -o progrw progrw.f parameter (inmax=100) c***** maximum number of lines to be read from file real x(inmax),y(inmax),yer(inmax) c***** define arrays of variables x,y,yer open(unit=2,file='mydata.dat') c***** open data file 'mydat.dat' in the current directory do i=1,inmax read(2,*,end=20) x(i),y(i),yer(i) c***** read one line at a time, going to 20 on reaching the end of file j=i c***** keep a note of lines read in end do 20 continue close(unit=2) c***** finished with file input unit write(6,*) j, ' lines have been read' c***** the unit number 6 is usually associated with screen output do i=1,j c***** now write out the variables which have been stored write(6,*)' line ',i,' has ',x(i),y(i),yer(i) end do end
to run this program, compile progrw.f and link to make progrw.exe
g77 -o progrw progrw.f
and run
progrw 10 lines have been read line 1 has 1.6860990E-03 464.5000 10.77613 line 2 has 4.1995151E-03 493.0833 6.410170 line 3 has 6.5153618E-03 476.0625 5.454714 line 4 has 9.1368612E-03 444.2500 3.983224 line 5 has 1.1507930E-02 496.5000 4.210955 line 6 has 1.3852740E-02 512.4167 3.772770 line 7 has 1.6353959E-02 510.4375 3.260999 line 8 has 1.8697230E-02 503.2954 3.382090 line 9 has 2.1087030E-02 493.0333 2.866570 line 10 has 2.3404090E-02 507.0179 3.008968
Clearly one wants more flexibility than just reading the file "mydata.dat". In the next example the reading and writing activities are localised in subroutines. Because there might be errors in the data it is useful to have a way of showing this.
To top
Program progrwm.f - written with Notepad
program progrwm c***** a simple program to read and write data using subroutines c R. Ghosh, ILL, version 1 October 2004 c g77 -o progrwm progrwm.f daread.f dawrit.f parameter (inmax=100) c***** maximum number of lines to be read from file real x(inmax),y(inmax),yer(inmax) c***** define arrays of variables x,y,yer call daread(x,y,yer,in,inmax) c***** routine reads in from file iout=6 call dawrit(x,y,yer,in,iout) c***** writes out to unit 6 (terminal) end
and a read routine daread.f
subroutine daread(xx,yy,yr,in,inmax) c****** routine to read from a 3 column data file c xx out first column value c yy out second column value c yr out third column value c in out number of lines read c inmax in maximum lines expected c R. Ghosh, Ill, October 2004 real xx(inmax),yy(inmax),yr(inmax) common/infile/fname character*100 fname c***** the filename to be read has a maximum length of 100 characters write(6,1) 1 format(' Give input filename : ',$) read(5,2) fname 2 format(a) open(unit=2,file=fname) do i=1,inmax read(2,*,err=25,end=20) xx(i),yy(i),yr(i) j=i end do 20 continue close(unit=2) c***** not required further - close input write(6,3) j 3 format(i3,' lines have been read in') in=j return 25 write(6,26)j 26 format(' daread - error after line ',i4) c***** when reading data it is useful to offer guidance on c potential errors therein stop end
and a write routine dawrit.f
subroutine dawrit(xx,yy,yr,nin,nunit) c****** routine to write out a 3 column data file c if nunit is 6 then output is to terminal c otherwise output is to a named file c c xx in first column value c yy in second column value c yr in third column value c nin in number of lines <=100 c nunit in output unit c R. Ghosh, ILL, October 2004 real xx(nin),yy(nin),yr(nin) common/oufile/fname character*120 fname c***** the filename to be read has a maximum length of 120 characters if(nin.gt.100) stop ' dawrit- cannot write more than 100 data' c***** all files treated by these routines should have less than 101 lines if(nunit.ne.6) then write(6,1) 1 format(' Give output filename : ',$) read(5,2) fname 2 format(a) end if c***** open a new file if(nunit.ne.6) open(unit=nunit,file=fname,status='new') c***** could use 'unknown' rather than 'new' if allow overwriting do i=1,nin write(nunit,*) xx(i),yy(i),yr(i) j=i end do if(nunit.ne.6) close(unit=nunit) c***** finished writing file output - close file write(6,3) j 3 format(i3,' lines have been written') return end
putting it all together
g77 -o progrwm progrwm.f daread.f dawrit.f progrwm Give input filename : mydata.dat 10 lines have been read in 1.6860990E-03 464.5000 10.77613 4.1995151E-03 493.0833 6.410170 6.5153618E-03 476.0625 5.454714 9.1368612E-03 444.2500 3.983224 1.1507930E-02 496.5000 4.210955 1.3852740E-02 512.4167 3.772770 1.6353959E-02 510.4375 3.260999 1.8697230E-02 503.2954 3.382090 2.1087030E-02 493.0333 2.866570 2.3404090E-02 507.0179 3.008968 10 lines have been written
To top
program progsub
c***** a simple program to read two data files and subtract c the second from the first, using subroutines c R. Ghosh, ILL, version 1 October 2004 c g77 -o progsub progsub.f daread.o dawrit.o parameter (inmax=100) c***** maximum number of lines to be read from file real x1(inmax),y1(inmax),yer1(inmax) real x2(inmax),y2(inmax),yer2(inmax) real x3(inmax),y3(inmax),yer3(inmax) c***** define arrays of variables x,y,yer call daread(x1,y1,yer1,in1,inmax) c***** routine reads in from file call daread(x2,y2,yer2,in2,inmax) c***** trivial check for compatibility if(in2.ne.in1) stop ' input files have differing lengths!' write(6,5) 5 format(' Give multiplier for second set of data [1.0] :',$) read(5,6) fmul 6 format(g12.6) if(fmul.eq.0) fmul=1.0 c c***** calculate difference and new error values c do i=1,in1 x3(i)=x1(i) c***** take first data as reference y3(i)=y1(i)-fmul*y2(i) yysq=yer1(i)**2+(fmul*yer2(i))**2 yer3(i)=sqrt(yysq) end do c c***** output results c iout=6 call dawrit(x3,y3,yer3,in1,iout) c***** writes out to unit 6 (terminal) iout=2 c***** output into a new file call dawrit(x3,y3,yer3,in1,iout) end
Reusing the routine from above:
g77 -o progsub progsub.f daread.f dawrit.f
or, because the compiled subroutines remain there:
g77 -o prgsub progsub.f daread.o dawrit.o
and test it..
progsub Give input filename : mydata.dat 10 lines have been read in Give input filename : mydata.dat 10 lines have been read in Give multiplier for second set of data [1.0] :-1.0 1.6860990E-03 929.0000 15.23975 4.1995151E-03 986.1666 9.065350 6.5153618E-03 952.1250 7.714130 9.1368612E-03 888.5000 5.633129 1.1507930E-02 993.0000 5.955190 1.3852740E-02 1024.833 5.335503 1.6353959E-02 1020.875 4.611749 1.8697230E-02 1006.591 4.782998 2.1087030E-02 986.0666 4.053942 2.3404090E-02 1014.036 4.255323 10 lines have been written Give output filename : newdata.dat 10 lines have been written
as a simple check the y data have doubled, and the error increased by a factor of 1.414 which is correct if the data are from two uncorrelated sets of counting events(SQRT(2.0))
To top
Plotting data using library routine RSPLT from library librlib.a which, in turn, calls Prof. Tim Pearson's PGPLOT library
program daplo c example of command line driven plotting program c R. Ghosh ILL, October 2004, version 1 c SGI f77 -o daplo daplo.f daread1.f librlib.a libpgplot.a -lX11 cMinGW g77 -o daplo daplo.f daread1.f librlib.a libpggw520.a -wl,subsystem,console -mwindows c c***** parameter (inmax=100) real x(inmax),y(inmax),yer(inmax) common/infile/filnam character*100 filnam,str character*50 title noargs=iargc() c***** gives number of fields in command line if(noargs.lt.1.or.noargs.gt.6) then write(*,*) 1' plot data : usage daplo filename ymin ymax xmin xmax' call exit end if
filnam=' ' str=' ' c***** set the whole string str to blanks call getargp(1,str) c***** this is first character string in command line - file name filnam=str call daread1(x,y,yer,nin,inmax) c***** daread1 will get filename from filnam iidev=1 call pgnopn(iidev,' ',ier) c***** open graphics if (ier.ne.0) stop 'no screen device PGPLOT_ILL_DEV_1' c***** put filename into title for plot title=str call rsplt(x,y,yer,nin,2,1,'X','Y',title) call pgnend(iidev) end
subroutine daread1(xx,yy,yr,in,inmax) c****** routine to read from a 3 column data file c xx out first column value c yy out second column value c yr out third column value c in out number of lines read c inmax in maximum lines expected c Input filename set in common/infile/fname c R. Ghosh, Ill, October 2004 real xx(inmax),yy(inmax),yr(inmax) common/infile/fname character*100 fname c***** the filename to be read has a maximum length of 100 characters open(unit=2,file=fname) do i=1,inmax read(2,*,end=20) xx(i),yy(i),yr(i) j=i end do 20 continue close(unit=2) c***** not required further - close input write(6,3) j 3 format(i3,' lines have been read in') in=j return end
build it g77 -o daplo daplo.f daread1.f librlib.a libpggw520.a -wl,subsystem,console -mwindows
now we can run this directly from the command line..
daplo sasteflon.dat

The batch file mingwvars.bat may be used as a shortcut to setting up a CMD program window used for development, modifying this shortcut to start in an appropriate test directory. Part of the g77 command line is setup as an environment variable %PGFLAG% simplifying the above command to:
g77 -o daplo daplo.f daread1.f librlib.a %PGFLAG%
To top
The command for building the program is getting rather complicated and a useful tool is gmake (GNU make) which uses a text "makefile" to build only those components which have been changed. The "target" (result) is denoted by the name+colon followed by the files used to create it. The following line has the appropriate command, starting with a colon. In the MinGW distribution the make program is initially named mingw32-make.exe
notepad makefile
all: daplo progsub progrwm daplo.exe: daplo.f daread1.o g77 -o daplo daplo.f daread1.o librlib.a libpggw520.a -wl,subsystem,console -mwindows daread1.o: daread1.f g77 -c daread1.f progsub.exe: progsub.f daread.o dawrit.o g77 -o progsub progsub.f daread.o dawrit.o progrw.exe: progrw.f daread.o dawrit.o g77 -o progrw progrw.f daread.o dawrit.o daread.o: daread.f g77 -c daread.f dawrit.o: dawrit.f f77 -c dawrit.f clean: del *.o
The command make daplo makes daplo.exe The command make all makes daplo.exe progsub.exe and progrw.exe The command make clean removes all the .o intermediate object files
To top
Introducing a fitting library - we can try fitting a gaussian curve Again we have the idea of a standard (or set of standard routines) to read in various types of data, and sets of calculation rouines to fit to the data using the library.
The MAIN program serves primarily to label the fitting parameters and select the reading and calculating routines.
PROGRAM FTEST C***** BASIC EXAMPLE ROUTINE FOR FITFUN C***** Link FTEST,MYREAD,GAUSS,FITFUN/LIB,LIBPG/LIB C HP setenv LPATH /lib:/usr/lib:/usr/local/lib:/usr/lib/X11R5 C HP f77 -o ftst ftst.o myread.o gauss.o libfitfun.a -lpgplot -lX11 -lU77 C IRIX f77 -o ftst ftst.o myread.o gauss.o libfitfun.a libpgplot.a -lX11 C MinGW f77 -o ftst ftst.o myread.o gauss.o libffn66m.a libpggw520.a \ C -wl,--subsystem,console -mwindows EXTERNAL MYREAD,GAUSS C C***** MYREAD IS A USER SUPPLIED ROUTINE TO READ IN ONE SPECTRUM EACH CALL C C***** GAUSS IS A USER'S ROUTINE TO CALCULATE THE REQUIRED FUNCTION C COMMON/TITLES/NAMES(40),TX,TY COMMON/TITLEP/NPARAS COMMON/WORK/W(30660) C***** THIS IS SUFFICIENT FOR 1600 DATA AND 10 PARAMETERS ! COMMON/VERSION/VERP C***** VERP IS TYPED BY THE PROGRAM INDICATING THE CURRENTLY RUNNING VERSION C CHARACTER*8 NAMES CHARACTER*4 PNAM CHARACTER*20 TX,TY C DATA NAMES/'CENTRE ','SIGMA','FLAT BAK','SLOPE', 1'HEIGHT',35*' '/ DATA PNAM/'ftst'/ DATA TX/'CHANNEL'/ DATA TY/'COUNTS'/ DATA NPARAS/5/ C VERP=2.0 CALL FITFUN(PNAM,MYREAD,GAUSS) C END
The calculation of a simple gaussian:
SUBROUTINE GAUSS(NPAR,PARM,NFIT,XUSE,YUSE,YRUSE,YCALC,F) C C CALC OF F AND YCALC FOR GAUSSIAN C DIMENSION PARM(NPAR) DIMENSION YCALC(NFIT),XUSE(NFIT),YUSE(NFIT) 1,YRUSE(NFIT),F(NFIT) C C The first parameter PARM(1) is the peak centre C PARM(2) is the peak deviation C PARM(3) is the flat background C PARM(4) is the sloping background C PARM(5) is the peak height C There are NFIT data values of Xuse Yuse and Yerror DO 10 I=1,NFIT C***** YCALC WILL CONTAIN CALCULATED FUNCTION FOR PLOTTING/LISTING YCALC(I)= PARM(5) * 1 EXP(-0.5*((XUSE(I)-PARM(1))/PARM(2))**2) 1 +PARM(3) + PARM(4)*XUSE(I) F(I)=YCALC(I)-YUSE(I) C***** F WILL BE MINIMISED BY the FITFUN LIBRARY by varying PARM(1-5) 10 CONTINUE C C RETURN END
subroutine myread(in,xx,yy,yr,ntext) c****** routine to read from a simple GSAS data file c xx out first column value c yy out second column value c yr out third column value c in out number of lines read c inmax in maximum lines expected c R. Ghosh, Ill, October 2004 parameter (inmax=1600) real xx(inmax),yy(inmax),yr(inmax) common/infile/fname character*100 fname c***** the filename to be read has a maximum length of 100 characters character ntext*(*) write(6,1) 1 format(' Give input filename : ',$) read(5,2) fname 2 format(a) open(unit=2,file=fname) c***** read title read(2,5) ntext 5 format(a) read(2,6) read(2,6) c***** skip 2 lines 6 format(1x) do i=1,inmax,5 read(2,*,end=20) (yy(n),yr(n),n=i,i+4) j=i end do 20 continue close(unit=2) do i=1,j xx(i)=i*0.1-2. end do c***** not required further - close input write(6,3) j 3 format(i3,' lines have been read in') in=j return end
We can add another few lines to the makefile ftest.exe: ftest.f myread.o gauss.o g77 -o ftest ftest.f myread.o gauss.o libffn66m.a libpggw520.a \ -wl,subsystem,console -mwindows myread.o: myread.f g77 -c myread.f gauss.0: gauss.f g77 -c gauss.f
and then use the command gmake ftest.exe then test it after reading in the data file S100.gsa
To top
A more complicated case allows one to fit up to four peaks using different model functions but sharing the read-in routine ff4.exe: ff4.f calskp.f calskpx.f g77 -o ff4 ff4.f myread.o calskp.f calskpx.f libffn66m.a libpggw520.a \ -wl,subsystem,console -mwindows
To top
These programs test data and libraries have been collated in a zip file together with a C version of the PGPLOT library and its header file cpgplot.h.
To top
|