## reference information

### brief introduction to modules

if you're not to familiar with modules, this page might be of interest

### tips & tricks

some things I keep forgetting. I wrote them down for me but they might be useful for you.

### fortran 90 references

- fortran 90: a conversion course for fortran 77 programmers , offered by the folks at the manchester computing centre. fairly complete although not comprehensive.
- fortran 90 for the fortran 77 programmer , offered by the national supercomputing center at jinköping university in sweden. quite complete and even includes fortran 77 information. works best if you already understand fortran 77. the authors also have a version in swedish.
- fortran 77 intrinsic function reference

### contact

I also have modules to perform matrix operations using sor, gauss-seidel, point-jacobi, and thomas algorithms. this is useful in finite-difference modeling of differential equations. email me if you want these.

## just the modules, thanks

### everything [ browse directory | tarball ]

everything listed below.

### datafile type [ source ]

automates the loading of data files from disk. instead of having to write custom list-based IO routines for every program that you write, you can just write two lines of code with this module that automatically reads in the file to a dynamically-sized array. current capabilities include interpolation, and I plan to add output to latex tables (no, the other kind) at some time in the future.

use datafile_type type(datafile) :: d integer :: i = 1 ! datafiles can contain one-line headers, where any number of spaces ! separate the column names. this allows you to later retrieve the ! data by header name and row number. datafile_type detects the ! presence of a header line if the first non-space character is not ! a valid numeric character ([0-9],+,-). when open() is called, the ! entire datafile is read in and stored. The upper limit to array ! size depends on how much memory you have. call open(d, 'datafile.txt'); do while (i<numrows(d)) ! numrows() is a datafile_type function write(*,*) get(d, i, 1) ! get() accesses the element from the ! 'i'th row and the first column end do ! you don't need to call close() on a datafile

other methods include:

`isgood(d)`

`.true.`

if datafile`d`

is properly initialized,`.false.`

otherwise.`getfname(d)`

the name of the file that produced datafile`d`

.`freeunit()`

a free unit number. extremely useful.`numrows(d)`

,`numcols(d)`

the number of rows or columns, respectively, in datafile`d`

.`get_header(d,i)`

the name of the header of the`i`

th column in datafile`d`

.

### steam tables [ tarball ]

uses the datafile_type module to load steam tables from disk and interpolate within them for water in the subcooled, saturated, and supercooled regions. quite handy. data obtained from NIST's Chemistry Web book site.

use steamtables call init() ! loads the steam tables into memory write(*,*) P_sat(500.) ! saturation pressure at 500 F write(*,*) T_sat(1000.) ! saturation temperature at 1000 psia ! enthalpy of saturated steam with a quality of 0.5 ! you may name any two of 'T=', 'P=', or 'x=' write(*,*) h_sat(T=500.,x=0.5) ! we can do superheated steam too write(*,*) u_sup(T=700.,P=1000.) ! or subcooled water write(*,*) u_sub(T=100.,P=14.7.)

The available properties are `T_sat`

, `P_sat`

, `u`

, `h`

,
`v`

, `Cv`

, `Cp`

, and `s`

for saturated steam and just `u`

,
`h`

, `v`

, and `s`

for subcooled and superheated water. For `T_sat`

and `P_sat`

you have to specify the corresponding property (`P`

and `T`

, respectively).
The other values require two parameters, `T`

and `P`

for subcooled and superheated states
and any two of `T`

, `P`

, or `x`

for saturation properties.

### math [ source ]

a few math routines, everyone's got their own toolkit. this particular one includes routines for numerical integration of functions and discrete data, differentiation, root finding, and calculation of error in trapezoidal integration.

use math ! data sets of some length real, dimension(:) :: x, y ! this block is necessary for the routines that operate on functions ! if f(x) is not defined in a module interface f real function f(x) real :: x end function f end interface write(*,*) derivative(f, 0.0) ! df/dx at x=0 write(*,*) newton(f,0.0) ! finds root of f(x) using newton's ! method, starting with a guess of x=0 write(*,*) bisection(f,-2.,2.)! finds root of f(x) using bisection. ! inefficient but always works. write(*,*) integral(f,0.,2.) ! integral of f from 0 to 2 using ! trapezoid summation write(*,*) trapz(x,y) ! integral of data set (x,y) using ! trapezoidal summation write(*,*) trapz_poisson_error(x,y) ! error associated with the summation ! (not with the data points themselves) write(*,*) sd(x) ! standard deviation of a data set

the trapezoidal functions also take arbitrary lower and upper bounds as third and fourth arguments.
the `set_epsilon`

subroutine sets the precision of many of the routines, and calling
`set_maxloop`

to something larger might help if you are getting 'maximum loops exceeded' errors.

### linear least squares [ tarball ]

a package to determine fit coefficients for a linear least-squares correlation on a set of data, along with error calculation. thanks to Dr. J. M. Doster for starting this project along.

use linear_least_squares ! x and y arrays of some length. yfit will hold values of the ! fit for each x. y_sd is the standard deviation of the y points. real, dimension(:) :: x, y, y_sd, yfit real, dimension(2) :: a, a_sd ! fit function of form y=a(2)*x+a(1) to (x,y). standard deviation of ! y values in y_sd, resulting standard deviations of fitting ! parameters a in a_sd. call lsq_linear(x,y,y_sd,yfit,a,a_sd) ! if you don't want all of that information, there are a couple of ! other ways to call it: ! no standard deviations call lsq_linear(x,y,yfit,a) ! no coefficient vector call lsq_linear(x,y,yfit) ! to fit a function of form y=a(1)*x, first make sure that ! a is an array of dimension 1 and: call lsq_linear_no_b(x,y,y_sd,yfit,a,a_sd) ! some arguments may be eliminated as above.

### matrix type [ source ]

I went a little crazy on this one. this module defines vector and matrix types and overloads the '+', '-', '*', and '**' operators for matrices. it also does inversion, transposition, and gauss-jordan elimination.

use vector_type type(vector) :: v1, v2 ! make v1 and v2 of length 5 call init(v1,5) call init(v2,5) v1%vData(1) = 4. ! v1(1) = 4 [...] ! add v1 and v2, take the dot product of the resulant vector and v1 write(*,*) (v1+v2)*v1 ! unfortunately, I did not overload the equals operator. don't know why, ! I must not have needed it.

use matrix_type type(matrix) :: m1, m2 ! set m1 and m2 to be of dimension 3x3 call init(m1,3,3) call init(m2,3,3) m1%mData(1,2)=3. ! m1(1,2)=3.

these modules aren't as accessible as the others, but they come in handy if you have
to do a lot of matrix operations. you access data elements directly by their associated arrays,
`vData`

in the case of vectors and `mData`

for matrices. the defined routines are:

`+`

,`-`

,`*`

vector and matrix operations, used just like their scalar counterparts`**`

inversion. if`m1`

is a matrix,`m1**(-1)`

is its inverse. the matrix dimensions have to be right or matrix_type will throw an error.`trans(m1)`

transposes matrix`m1`

. returns a new matrix.