next_inactive up previous


GO - General Objects library

ARJO SEGERS
KNMI


Date: 3 March 2009


Contents

Introduction

The GO library provides general purpose entities for Fortran90 programs.

In summary, the GO library provides:

The library consists of a single module to provide access to routines, functions, and data types. In addition, a few shell scripts are provided for specialized tascs.

About status argument

An integer status argument is present in most routines:

     subroutine aaa( status )

      integer, intent(out)  ::  status

      ! wrong!
      if ( 1 /= 0 ) then
        write (*,'("ERROR - this is a serious error ...")')
        write (*,'("ERROR in aaa"); status=1; return
      end if

      ! ok
      status = 0

    end subroutine aaa
The value should be checked on return to test on succesful completion:
    call aaa( status )
    if (status/=0) then; write (*,'("ERROR in prog")'); status=1; return; end if
To make the make the code more readible, define a preprossor macro for this check-and-trace line:
    #define IF_ERROR_THEN(action) if (status/=0) then; write (*,'("ERROR in prog")'); action; return; end if

    call aaa( status )
    IF_ERROR_RETURN( status=1 )

GO

The GO-library takes the form of a module:

     use GO

The GO module (source file go.f90) is in fact a shell around a bunch of sub modules. The sub modules should not be used directly, but accessed through the main module only.

GO_FU

Description

Standard file units, might be compiler depended.

Since the standard file units might be used by other modules to write (error) messages, this is the most basic of all GO modules.

Usage

Access the entities of this module via the main module (prefered) or directly:

       use GO, only : ...
       use GO_FU, only : ...

Constants

Hackers only

The module is implemented in source file go_fu.F90 .

GO_Print

Description

Tools for (error) messages.

Basic idea is to write messages to the character buffer 'gol' and let the the actual printing be managed by a special routine. This is especially usefull if the program runs on multiple processors:

       write (gol,'("This is processor : ",i2)') myid; call goPr
With the appropriate settings, the output might be:
       [00] This is processor :  0
       [03] This is processor :  3
       [02] This is processor :  2
       [01] This is processor :  1

Usage

Access the entities of this module via the main module (prefered) or directly:

       use GO, only : ...
       use GO_Print, only : ...

Variables

Procedures

To be done

The following options should be implemented soon, since they have been implemented in older versions:

Hackers only

The module is implemented in source file go_print.f90 .

GO_String

General objects for character strings.

Usage

Access the entities of this module via the main module (prefered) or directly:

       use GO, only : ...
       use GO_String, only : ...

Procedures

Hackers only

The module is implemented in source file go_string.F90 .

GO_Date

General objects for date manipulation.

Usage

Access the entities of this module via the main module (prefered) or directly:

       use GO, only : ...
       use GO_Date, only : ...

Derived types

A derived type is provided to store a date:

       type(TDate)     ::  t
with fields:
       character(len=4)   ::  calender     ! see 'calenders'
       integer            ::  year, month, day, hour, min, sec, mili

A second type is defined for time steps:

       type(TIncrDate)    ::  dt
with fields for days, hours, minutes, seconds, and mili-seconds. The fields of an incremental data might have any value, even negative. Note that for this type a value day=1 has the interpretation of 24 hours, while it has the interpretation of 'first day', thus 0 hours, for a regular date.

Calenders

A number of different calender types is supported:

Creating date structures

To initialize a new date structure, a few routines are available.

Use routine NewDate to initialize some fields and to fill the rest with zero's. If no calender is specified, the default value 'greg' is used (see section about defaults).

       t = NewDate( year=2000, month=1, ..., calender='greg' )
Interface:
       function NewDate( year, month, day, hour, min, sec, mili, zone, calender )
         type(TDate)                              ::  NewDate
         integer, intent(in), optional            ::  year, month, day
         integer, intent(in), optional            ::  hour, min, sec, mili
         integer, intent(in), optional            ::  zone
         character(len=*), intent(in), optional   ::  calender
       end function NewDate
Use the specific order of the optional fields to quickly set the 'largest' values only, for example the date:
       t = NewDate( 2000, 1, 2 )
A special funtion creates a date that represents 'any' time; useful to specify that some data is constant in time and thus valid for any time. A special inquiry function is available to test wether a date is any:
       t = AnyDate()
       l = IsAnyDate(t)

Use routine IncrDate to create an incremental date:

       t = IncrDate( day=2, hour=12 )
Interface:
       function IncrDate( day, hour, min, sec, mili )
         type(TIncrDate)                  ::  IncrDate
         integer, intent(in), optional    ::  day, hour, min, sec, mili
       end function IncrDate

Fill the time from the system clock in a date structure; the result is of calender type 'wall':

       t = SystemDate()

Changing date fields

Use the Set routine to set some specific fields of a date structure:

       call Set( t [,year=2000] [,month=1] [,day=2]          &
                   [,hour=0] [,min=0] [,sec=0] [,mili=0]     &
                   [,zone=0] [calender='greg'] )
Use the specific order of the optional fields to quickly set the 'largest' values only, for example the date:
       call Set( t, 2000, 1, 2 )

Normalize hours to 0,..,23, minutes to 0,..,59, etc:

      call Normalize( t )

To check if all fields are consistent with eachother, use:

       call Check( t )

Similar routines are implemented for date increments.

Extraction of date fields

Use the Get routine to extract some specific fields of a date structure:

       call Get( t [,year=year] [,month=month] [,day=day]              &
                   [,hour=hour] [,min=min] [,sec=sec] [,mili=mili]     &
                   [,zone=zone] [calender=calender] )
Use the specific order of the optional fields to quickly extract the 'largest' values only, for example the date:
       call Get( t, year, month, day )

A similar routine is implemented for date increments.

Inquiry functions

A few inquiry functions are provided.

The logical function LeapYear tells you if the year has a Februari 29 :

       l = LeapYear( t )

Two integer functions are provided to count the total number of days in a month or a year:

       i = Days_in_Month( t )
       i = Days_in_Year( t )

An integer function is provided to return the day number, counting from 1 (Januari 1) to 360, 365, or 366 (last of December):

       i = DayNumber( t )

Operators

Operator + is redefined to be able to add two dates to each other. Both should be of same calender type, unless one is an increment:

        to =  t1 +  t2
        to =  t  + dt
       dto = dt1 + dt2

Operator - is redefined to substract a date from another. Both should be of same calender type, unless the substracted date (t2) is an increment:

        to =  t1 -  t2
        to =  t  - dt
       dto = dt1 - dt2

Operator * has been redefined to multiply a date increment with a real or integer number. If necessary, a remaining fraction of miliseconds is rounded to the nearest integer.

       dto = dt * 2
       dto = 2 * dt
       dto = dt * 1.5
       dto = 1.5 * dt

Operator / is redefined to devide a date incrment by a real or an integer number. If necessary, a remaining fraction of miliseconds is rounded to the nearest integer.

       dto = dt / 2
       dto = dt / 1.5

Logical operators are defined to compare two dates with eachother; both should be of same calender type:

       t1 == t2
       t1 >= t2
       t1 >  t2
       t1 <= t2
       t1 <  t2

Summation routines

The total number in a certain unit is returned by rTotal (real value) or iTotal (integer value, error if the sum could only be expressed as fraction). Currently supported units are 'year', 'month', 'day', 'hour', 'min', 'sec', and 'mili'. If the total number is not wel defined for a certain date (how to assign a fraction of years to the date of today?), an error message is produced. Date increments are supported too.

       r = rTotal( t, 'year'|'month'|... )
       i = iTotal( t, 'year'|'month'|... )

Temperal interpolation

A linear interpolation in time is represented by:

       f(t) = alfa1 * f(t1) + alfa2 * f(t2)
Given the dates t, t1, and t2, the fractions alfa1 and alfa2 are set by the following routine:
       InterpolFractions( t, t1, t2, alfa1, alfa2, status )
         type(TDate), intent(in)    ::  t
         type(TDate), intent(in)    ::  t1
         type(TDate), intent(in)    ::  t2
         real, intent(out)          ::  alfa1
         real, intent(out)          ::  alfa2
         integer, intent(out)       ::  status

Output

To obtain a pretty formatted print of the value of a date, the 'Pretty' routine is provided. Output differs based on the calender type. Also implemented for date increments.

       character(len=36) function Pretty( t )
         type(TDate), intent(in)    ::  t

       calender                      output
       ----------------------------  ----------------------------------------
       (date)
         'wall'                       1:23:45:678 03 feb 2001 (GMT+02:00)
         'greg', '366', '365', '360' 2001/02/03  1:23:45:678
       (date increment)              
                                      2 days  1:23:45:678

Two routines are provided to write messages including a date to the 'gol' buffer from the 'GO_Print' library. Add a call to 'goPr' or 'goErr' to actually display the message. Example:

       call wrtgol( 'time  : ', t ); call goPr
       call wrtgol( 'range : ', t1, ' - ', 't2' ); call goPr
provides:
       [00] time  : 2001/01/01 00:00:00:000
       [00] range : 2001/01/01 00:00:00:000 - 2001/01/01 03:00:00:000

Defaults

For setting some default values, the subroutine 'go_DateDefaults' is available. All arguments are optional. Yet, only the calender type might be set.

       call goDateDefaults( [calender='greg'] )

Hackers only

The module is implemented in source file go_date.F90 .

GO_File

Selects free file units.
Read lines from a commented text file, skipping comments and empty lines.

Usage

Access the entities of this module via the main module (prefered) or directly:

       use GO, only : ...
       use GO_File, only : ...

Free file unit

Use the following routine to select a free (unopened) file unit:

       call goGetFU( fu, status )
         integer, intent(inout)    ::  fu
         integer, intent(out)      ::  status
The routines searches for unopened file units with the range specified by 'goFuRange' from module 'GO_FU', excluding the standard units. If all units are already opened, an error message is returned.

Commented text files

A commented text file might look like:

       !
       ! This is data file.
       ! 

       ! number of data values:
       NDATA
       3

       ! data values:
       DATA
       1.0 2.0 3.0
To be able to read from this file without bothering about comments and empty lines, a special file type is introduced:
       type(TTextFile)    ::  file

To open the file, use:

       subroutine Init( file, 'data.txt', iostat, status, comment )
         type(TTextFile), intent(out)              ::  file
         character(len=*), intent(in)              ::  filename
         integer, intent(out)                      ::  iostat
         character(len=*), intent(in), optional    ::  status
         character(len=1), intent(in), optional    ::  comment
The 'iostat' argument is the 'usuall' status argument, thus on return non-zero in case of errors. The 'status' argument is the same as used by Fortran's 'open' command to specify wether a file should already exist (status='old'), should not exist yet and will be created ('new') or might exist or not ('unknown').

The optional comment is a single character; lines in the file that start with this character are skipped while reading.

To close the file, use:

       subroutine file_Done( file, status )
         type(TTextFile), intent(inout)    ::  file
         integer, intent(out)              ::  status

To read one line, skipping empty and comment lines, use:

       subroutine ReadLine( file, s, status  )
         type(TTextFile), intent(inout)      ::  file
         character(len=*), intent(out)       ::  s
         integer, intent(out)                ::  status
Return status<0 means that no values are read since end of file is reached; errors are indicated by status>0.

Hackers only

The module is implemented in source file go_file.F90 .

GO_Rc

Read settings from a resource file.

Resource files

In the GO library, an 'rcfile' or 'resource' file is a text file with settings for a program, with a format following the X-resource conventions:

       ! This is an example resource file.
       ! Use line of the form:
       !
       ! <name> : <value>
       !
       ! Some conventions:
       !   * comment lines start with '!'
       !   * logical values are 'T' or 'F'  (without quotes ...)
       !   * character strings do not contain quotes

       prog.n            :  20
       input.file        :  /data/test.dat
       prog.debug        :  T

Derived types

A type has been derived to get access to a rcfile:

       type TrcFile

Routines

To open a rcfile, use:

       subroutine Init( rcfile, fname, status )
         type(TrcFile), intent(out)    ::  rcfile
         character(len=*), intent(in)  ::  fname
         integer, intent(out)          ::  status
To close it again, use:
       subroutine Done( rcfile,  status )
         type(TrcFile), intent(inout)    ::  rcfile
         integer, intent(out)            ::  status

To read the value asigned to a key, use:

       subroutine ReadRc( rcfile, key, x, status, default )
         type(TrcFile), intent(in)                   ::  rcfile
         character(len=*), intent(in)                ::  key
         <type>, intent(out)                         ::  x
         integer, intent(out)                        ::  status
         <type>, intent(in), optional                ::  default
Current implemented types:
       <type>  =  integer|real|character(len=*)|logical
If a key has not been found, an error messages is returned unless a default is provided.

See also

The shell scripts 'go_readrc' and 'go_pprc' are available to read from a rcfile withing shell scripts and to preprocess the rcfile respectively.

Hackers only

The module is implemented in source file go_rc.F90 .

GO_System

Description

Interface to routines of some common system routines. These routines are not part of the Fortran standard, but almost always supplied. There might be subtile compiler (vendor) specific differences however, and therefor this module was made. Preprocessor statements in select the compiler specific code.

Currently only implemented for:

Usage

Access the entities of this module via the main module (prefered) or directly:

       use GO, only : ...
       use GO_System, only : ...

Procedures

Hackers only

The module is implemented in source file go_system.F90 .




next_inactive up previous
TM5 2009-03-03