Wednesday, February 26, 2014

IDL systax

Assignment
Syntax: Variable = expression
eg:
  x = 7
  num = [12,32,52,12]
 

If
Syntax:

   way1: 
        if expression then statement

   way2:
       if expression then statement1 else statement2

   way3: 
       if expression then begin
           statement1
       endif  
    way4: 
       if expression then begin
           statement1
       endif else be  begin
           statement2
      endelse
     
eg:
if y lt 0 then t=2

if y lt 0 then t=2 else t=3

if y lt 0 then begin
    t=2
   txt='Negative'
endif

if y lt 0 then begin
    t=2
   txt='Negative'
endif else begin
    t=3
   txt='Non-negative'
endelse

if ((x gt -2) and (x lt 3)) and ((y gt 5) and (y lt 8)) then t=2

For Loops
Syntax: 

     for variable = init, limit, step do statement
eg:
for i=0,9 do print,i

for t=1.0, 0.01, -.01 do plots,x*t,y*t

for ix=0L, n, 10 do begin
   x(j) = xx(ix)
   j = j+1
   print,ix
endfor

While Loops
Syntax: 

    while expression do statement
eg:
while x gt 0 do x=x-1
 

while not eof(lun) do begin
    readf,lun,txt
    print,txt
endwhile


Repeat Loops
Syntax: 


      repeat statement until expression
 

eg:
 repeat x=x-1 until x le 0

repeat begin
   readf, lun, x
    x = x-c
endrep until x le 0

Case
Syntax:
   case expression of
       expression: statement
         . . .
        expression: statement
        else: statement
   endcase

eg:
case animal of
    'cat': print,'meow'
    'dog': print,'arf arf'
    'bird': print,'tweet tweet'
    else: print,'??'
endcase

Goto
Syntax: 

    goto, label
 

eg: 
 . . .
loop:
. . .
goto, loop

. . .
goto, err
. . .
err: print,' Error ...'
. . .

Blocks
    Syntax:

      begin
        statement 1
        . . .
        statement n
      end
     
eg:
        if x lt 0 then begin print,x & a=2 & endif

        for i=0, 10 do begin readf, lun, txt & print,txt & endfor

Common

Purpose: Share variables between routines or remember values between calls to a routine. 

Syntax: 
        common     name, variable_1, variable_2, . . . variable_n,

name is the name of the common block. Variables are matched by position so need NOT have the same name in each routine.
eg:
        common xkodak_com, x, y, dx, dy, file, count
        common random_plot_com, seed

Notes: 

      A single routine may use a common to save the value of a variable between calls.
      To remember default values,
      to remember a seed value for the randomu function

    Several routines may use a common to share status values.
    In such cases it is useful to store the common in a separate file and
    include it in each routine (@filename where @ is in column 1).
    This way only a single copy of the common need be maintained.

    A good way to name commons is to use the main routine name followed by _com,
    like xkodak_com. This helps prevent the accidental use of the same name for
    diffrent commons.

Procedure definition
 Syntax: 

      pro     name, parameter_1, parameter_2, ... parameter_n

 Note:    name is the name of the procedure.
eg:

Definition:
        pro test, a, b, c

        pro compute, x, y, z, flag=flg, help=hlp

    Notes: A procedure must end with an "end" statement and MAY have one or more return statements inside.
    If program flow reaches the final end statement a return is implied.

Calling procedure:
    test, 2, 3, out
    compute, x, y, z, /flag

Function definition
    Purpose: Specify a function name and parameters.
Syntax: 

       function     name, parameter_1, parameter_2, ... parameter_n
    name is the name of the function.
eg:
        function test, a, b, c
        function compute, x, y, z, flag=flg, help=hlp

Notes: A function must end with an end statement and MUST have one or more return 

statements inside.     
A return statement in a function must include the return value: return, value.
eg:
    a = test(2, 3, 5)
    t = compute(x, y, z, /flag)

IDL data structure

a) A named structure
is created by executing a structure-definition expression, which is an expression of the following form:

{Structure_Name,
  Tag_Name1 : Tag_Definition1,
   ...,
  Tag_Namen : Tag_Definitionn}

b) Anonymous structures
 are created in the same way, but with the structure’s name omitted.

{Tag_Name1 : Tag_Definition1 ,
     ...,
    Tag_Namen : Tag_Definitionn}

c)  Example
1) A named data structure example:
A = {star,           $           ; star is the structure name. 
     name  : '',     $           ; A is a variable of type star.       
     ra    : 0.0,    $ 
     dec   : 0.0,    $
     inten : FLTARR(12)}
 
2) Anonymous data structure example: 
way 1: 
A = {                $  
     name  : '',     $
     ra    : 0.0,    $ 
     dec   : 0.0,    $
     inten : FLTARR(12)}

 way 2: 
A = CREATE_STRUCT('name',    '',      $
                                          'ra',        0.0,   $
                                          'dec',     0.0,   $   
                                           'inten'FLTARR(12)) 
 

Data structure for observed FMSDR files or simulated BT files in MIRS

SDR : calibrated and earth-located Sensor Data Records
EDR : Environmental Data Records

  1. Radiance files: 
 "io_measur.pro"

; read in header (ReadRadHdr: 7 elements)
    readu,iu, nMeasurData
    readu,iu, nchan
    readu,iu, nPosScan,  nScanLines
    readu,iu, nqc 

    readu,iu,  cfreq
    readu,iu,  polar

; read in body (ReadRad : 13 elements)
    readu,iu,     lat(iprof),   lon(iprof),  RelAziAngle(iprof), SolZenAngle(iprof),
    readu,iu,    direc(iprof), iscanPos(iprof), iscanLine(iprof), Year(iprof),  Day(iprof),  time(iprof),
    readu,iu,    angle(iprof,0:nchan-1)
    readu,iu,    tb(iprof,0:nchan-1)
    readu,iu, qc(iprof,0:nqc-1)=qc0(0:nqc-1)


; Anonymous data structure
;======================================================================================
  ;---Set Up the Rad structure
Rad={ $
;----Header
nfilesRad         : nfilesRad,          $ ;Number of files
nProf               : nprof,                 $ ;Number of profiles
nchan               : nchan,                $ ;Number of channels
nPosScan         : nPosScan,          $ ;Number of scan positions
nScanLines      : nScanLines,       $ ;Number of scan lines
nqc                   : fltarr(nfilesRad),  $ ;Size of QC vector
Cfreq                : cfreq,                $ ;Central frequencies
Polarity            : polar,                 $ ;Polarizations
tb                      : fltarr(nfilesRad,nProf,nchan), $ ;Array of TBs
Angle               : fltarr(nfilesRad,nProf,nchan), $ ;Array of viewing angles
RelAziAngle    : fltarr(nfilesRad,nProf),   $ ;Array of relative azimuth angles
SolZenAngle    : fltarr(nfilesRad,nProf),   $ ;Array of solar zenith angles
Lat                    : fltarr(nfilesRad,nProf),  $  ;Array of latitude
Lon                   : fltarr(nfilesRad,nProf),   $ ;Array of longitude
Direc                 : intarr(nfilesRad,nProf),  $ ;Array of orbot mode flags
ScanPos            : intarr(nfilesRad,nProf), $ ;Scan positions
ScanLine           : intarr(nfilesRad,nProf), $ ;Scan lines
Year                   : lonarr(nfilesRad,nProf), $ ;Year
Day                    : lonarr(nfilesRad,nProf), $ ;Day
Time                  : fltarr(nfilesRad,nProf), $ ;UTC Time
Hours                 : fltarr(nfilesRad,nProf), $ ;Hours      (extended from Time)
Mins                   : fltarr(nfilesRad,nProf), $ ;Minutes  (extended from Time)
Secs                    : fltarr(nfilesRad,nProf), $ ;Seconds  (extended from Time)
qc                        : intarr(nfilesRad,nProf,14) $ ;QC information
}

2. EDR format (scene files ) 
Scene={                                        
    ;----Header
       algSN:algSN,                                readu,iu,algSN
       iTyp:iTyp,                                  readu,iu,iTyp
       nProf:nPrf,                                 readu,iu,nPrf
       nProfsProcessed:0L, not from scene file,    Num of profs read successfully                       nLay:nLay,                                  readu,iu,nLay
       nLev:nLev,                                  readu,iu,nLev
       nChan:nChan,                                readu,iu,nChan
       nScanPos:nPosScan,                          readu,iu,nPosScan
       nScanLines:nScanLines,                      readu,iu,nScanLines
       nAbsorb:nAbsorb,                            readu,iu,nAbsorb
       nParmCLW:nParmCLW,                          readu,iu,nParmCLW
       nParmRain:nParmRain,                        readu,iu,nParmRain
       nParmSnow:nParmSnow,                        readu,iu,nParmSnow
       nParmIce:nParmIce,                          readu,iu,nParmIce 
       nParmGrpl:nParmGrpl,                        readu,iu,nParmGrpl
       absorbID:absorbID2use4Declaration, A        AbsorbID=lonarr(nAbsorb), readu,iu,absorbID
       cFreq:cFreq,                       A        cfreq=fltarr(nChan), readu,iu,cFreq
       polarity:polar,                    A        polar=lonarr(nChan), readu,iu,polar
       nQC:nQC,                                    readu,iu,nQC
       declarN_Prf:nPrf,    duplicate value        nPrf
    ;----Body of Scene file  ( all FOVs )
       profIndxVec:  intarr(nPrf),        A    readu,iu, profIndx
       PresLayVec:   fltarr(nPrf,nLay),   AA   fltarr(Nlay), readu,iu, pressLay
       presLevVec:   fltarr(nPrf,nLev),   AA   fltarr(nLev), readu,iu, pressLev
       tempLayVec:   fltarr(nPrf,nLay),   AA   fltarr(Nlay), readu,iu, tempLay
       absorbLayVec: fltarr(nPrf,nLay,2), AA   fltarr(nAbsorb), readu,iu,absorbents
       tpwVec:       fltarr(nPrf),        A    DERIVED. !!!
       rhVec:        fltarr(nPrf,nLay),   A    DERIVED. !!!
       clwLayVec:    fltarr(nPrf,nParmCLW)AA   fltarr(nParmCLW), readu,iu, xCLW 
       clwVec:       fltarr(nPrf),        A    DERIVED. !!!
       rwpVec:       fltarr(nPrf),        A    DERIVED  !!!
       iwpVec:       fltarr(nPrf),        A    NOT SET  !!!
       gwpVec:       fltarr(nPrf),        A    DERIVED  !!!
       swpVec:       fltarr(nPrf),        A    NOT SET  !!! 
       rainLayVec:   fltarr(nPrf,nParmRain),AA fltarr(nParmRain), readu,iu, xRain
       snowLayVec:   fltarr(nPrf,nParmSnow),AA 0.0  (hard-coded)
       IceLayVec:    fltarr(nPrf,nParmIce), AA 0.0  (hard-coded)
       grplLayVec:   fltarr(nPrf,nParmGrpl),AA fltarr(Scene.nParmGrpl), readu,iu, xGrpl 
       anglVec:      fltarr(nPrf),          A  readu,iu, angl
       relAziAnglVec:fltarr(nPrf),          A  readu,iu, relAziAngl
       solZenAnglVec:fltarr(nPrf),          A  readu,iu, solZenAngl
       emissVec:     fltarr(nPrf,nChan),    AA fltarr(Scene.nchan), readu,iu, emiss
       reflVec:      fltarr(nPrf,nChan),    AA NOT SET !!!
       windSpVec:    fltarr(nPrf),          A  readu,iu, windSp
       windUVec:     fltarr(nPrf),          A  readu,iu, windU
       windVVec:     fltarr(nPrf),          A  readu,iu, windV 
       tskinVec:     fltarr(nPrf),          A  readu,iu, tSkin
       snowDepthVec: fltarr(nPrf),          A  readu,iu, snowDepth
       sfcPressVec:  fltarr(nPrf),          A  readu,iu, sfcPress
       sfcTypVec:    intarr(nPrf),          A  readu,iu, sfcTyp
       QC:           intarr(nPrf,nqc),      AA intarr(Scene.nqc), readu,iu, qc
       lat:          fltarr(nPrf),          A  readu,iu, lat
       lon:          fltarr(nPrf),          A  readu,iu, lon 
       direc:        intarr(nPrf),          A  readu,iu, node  (asc, desc)
       time:         fltarr(nPrf),          A  readu,iu, scanUTC
       year:         intarr(nPrf),          A  readu,iu, scanYear 
       day:          intarr(nPrf),          A  readu,iu, scanDay
       hours:        fltarr(nPrf),  DERIVED A  fix(scanUTC/3600.)  !!!
       mins:         fltarr(nPrf),  DERIVED A  fix( ( time - fix(Hours) * 3600. )/60.)  !!!
       secs:         fltarr(nPrf),  DERIVED A  (Time - Hours*3600. - Mins*60.)   !!!
       nAttempt:     intarr(nPrf),    COD   A  readu,iu, nAtt
       nIter:        intarr(nPrf),    COD   A  readu,iu, nIter
       chiSq:        fltarr(nPrf),    COD   A  readu,iu, chiSq
       yFwd:         fltarr(nPrf,nChan),COD AA fltarr(Scene.nchan), readu,iu,yFwd
       chanSel:      lonarr(nPrf,nChan),COD AA lonarr(Scene.nchan), readu,iu,chanSel
       ym:           fltarr(nPrf,nChan),COD AA fltarr(Scene.nchan), readu,iu,ym
       ymCorr:       fltarr(nPrf,nChan),cOD AA fltarr(Scene.nchan), readu,iu,ymCorr
       scanPos:      lonarr(nPrf),          A  readu,iu, iScanPos
       scanLine:     lonarr(nPrf)           A  readu,iu, iScanLine
  }
 
NOTE: 
1. Condition : COD
   COD: if Scene.iTyp eq 1 

howt to set up MIRS


How  to setup mirs?
Note: these steps below are intended to run part of mirs system to generate observation BT only and compare it with simulated BT that is generated using gfs 6-hr frorecast.
1.       Check out MIRS code
$ cd     # go to /data/home001/dxu
$ cd mirs_trunk
2.       Compile the code ( directory is relative to MIRS_ROOT )
$ cd   /data/home001/dxu/mirs_trunk/setup
$ vi paths      # set up MIRS_ROOT to /data/home001/dxu/mirs_trunk
$ cd   /data/home001/dxu/mirs_trunk/src/crtm/REL-2.1.1/configure
$ source   ifort.setup
$ cd   /data/home001/dxu/mirs_trunk/src/crtm/REL-2.1.1
$ make     # compile CRTM lib
Note: create libCRTM.a  under “libsrc” folder under the current folder.
$ make  install   # create includes
note: move crtm library to “lib” folder and  mod files to “includes” folder.
$ cd    /data/home001/dxu/mirs_trunk/src     # compile whole mirs library  and generate all the executable files
$ make
Note: executables files are under “bin” folder.
3.       Run mirs
$ cd   /data/home001/dxu/mirs_trunk/gui
$ make   
Note: compile java gui code.
$ make run   # gui pop-out
Note: specify scripts and config file to run mirs, which is part of the entire mirs.
3.1 configuration


3.2 Run mirs
Click button “ generate script”
Note:  generate two files:

    setup/f18_pcf.bash
    script/f18_scs.bash

3.3 Output location:
Observation data :
/data/home001/dxu/mirs_trunk/data/TestbedData/DynamicData/fmsdr/f18_ssmis/2013-01-20
FMSDR: footprint matched sensor data record.
Interpolated gfs 6-hr forecast data that is input to CRTM :
/data/home001/dxu/mirs_trunk/data/TestbedData/DynamicData/nwp_analys/f18_ssmis/2013-01-20
Simulated BT data :
/data/home001/dxu/mirs_trunk/data/TestbedData/DynamicData/fwd_analys/f18_ssmis/2013-01-20
Bias file :
/data/home001/dxu/mirs_trunk/data/SemiStaticData/biasCorrec
Eg: biasCorrec_f18_2013_01_20.dat_gfs

3.4 Data structure of binary data that are generated for both MIRS observed BT and simulated BT.
"IO_MeasurData.f90"  under /data/home001/dxu/mirs_trunk/src/lib/io ) :
MeasurData_type : tb       
   !Brightness temperatures
SUBROUTINE ReadHdrMeasurmts    : ## read header first
SUBROUTINE ReadMeasurmts(iu,Y,ierr)  : ## then to read BT.
IDL equivalent code to read BT:
"io_measur.pro" under /data/home001/dxu/mirs_trunk/src/lib_idl : 
Name:         LoadRadFile
3.5 Data structure of bias file :
IDL equivalent code to read bias file:
"io_measur.pro" under /data/home001/dxu/mirs_trunk/src/lib_idl
Name:         ReadBias

Friday, February 21, 2014

How to setup GSI code on s4

-----------------------------------------
1. Check out the latest GSI version
 -----------------------------------------
$ cd
$ svn co https://svnemc.ncep.noaa.gov/projects/gsi/branches/NESDIS-JCSDA/users/dxu/gsi  gsi_dxu

-----------------------------------------
2. Load modules needed to compile code
 -----------------------------------------
$ cd
$ module purge
$ module load  license_intel
$ module load  intel/12.1
$ module load  hdf5
$ module load  netcdf4/4.2.1
$ module load  impi/4.0.3.008

-----------------------------------------
3. Compile new GSD code. 
 -----------------------------------------
$ cd /home/dxu/gsi_dxu/lib/GSD/gsdcloud4nmmb
$ make
Note: libgsdcloud.a is created under the same location.

-----------------------------------------
4. Compile CRTM code ( version CRTM_REL-2.1.3 )
 -----------------------------------------
$ cd /home/dxu/gsi_dxu/lib/CRTM_REL-2.1.3
$  .    configure/ifort.setup
$ make
Note: Create libCRTM.a, mod files and object files in "libsrc" folder

$ make install
Note:
   Copy libsrc/libCRTM.a to /home/dxu/gsi_dxu/lib/CRTM_REL-2.1.3/lib
   Copy libsrc/*.mod to /home/dxu/gsi_dxu/lib/CRTM_REL-2.1.3/include

$ make clean
Note: remove libCRTM.a, mod files and object files from "libsrc" folder


-----------------------------------------
5. Link CRMT coefficient files
 -----------------------------------------
$ cd    /home/dxu/gsi_dxu/lib/CRTM_REL-2.1.3/fix
$ make   Big_Endian
$ cd    /home/dxu/gsi_dxu/scripts
$ sh   link_crtm_coeffs.sh 
  /usr/local/jcsda/NESDIS-JCSDA/gsi2014/lib/CRTM_REL-2.1.3/fix 
  /home/dxu/gsi_dxu/lib/CRTM_REL-2.1.3/fix/Big_Endian

Note: Link all the coefficient files in "Big_Endian" under various categories
      such as "TauCoeff" to /home/dxu/gsi_dxu/lib/CRTM_REL-2.1.3/fix/Big_Endian folder,
      to which so running scripts need to access to avoid specifying specific sub-dir.
      Not sure this step is necessary since in Makefile.conf we use centralized CRTM and
      we expect that running scripts will get everything including coefficient files from
      that centralized CRTM location instead of getting data locally.

      eg:
         zssmis_f19.TauCoeff.bin ->  /usr/local/jcsda/NESDIS-JCSDA/gsi2014/lib/
              CRTM_REL-2.1.3/fix/TauCoeff/ODPS/Big_Endian/zssmis_f19.TauCoeff.bin

----------------------------------------- 
6. Get modified Makefile and config file
   from centralized location.

-----------------------------------------
$ cd   /home/dxu/gsi_dxu/src
$ cp   /usr/local/jcsda/NESDIS-JCSDA/gsi2014/src/Makefile   .
$ svndiff   Makefile
    -COREROOT = ../../..
    +COREROOT = /usr/local/jcsda/NESDIS-JCSDA/nceplibs2012

# Makefile.conf is similar to Makefile.conf.s4
$ cp    /usr/local/jcsda/NESDIS-JCSDA/gsi2014/src/Makefile.conf .

# Modify to use GSD and CRTM library compiled above.
$ vi   Makefile.config

-----------------------------------------
7. Compile GSI
-----------------------------------------
$ cd   /home/dxu/gsi_dxu/src
$ make  -f   Makefile

Note: global_gsi is created under the same directory.

library summary

1. Shared library (so name  / soname )












eg: 
fully-qualified soname   :   libnetcdf.so -> libnetcdf.so.7.2.0
soname                         :   libnetcdf.so.7 -> libnetcdf.so.7.2.0
real name                     :   libnetcdf.so.7.2.0

2. Display a list of object from libraries. 
    2.1 List objects from shared library
    $ readelf   -s    libnetcdf.so

    2.2 List objects from static library
    $ ar -t  libcomp.a

Thursday, February 20, 2014

f90 intrinsic functions

APPENDIX 5

Intrinsic functions in Fortran 90

Introduction

There is a large a number of intrinsic functions and five intrinsic subroutinesin Fortran 90. I treat the numeric and mathematical routines very shortly, since they are not changed from Fortran 77 and therefore should be well-known. This section is based on section 13 of the ISO standard (1991), which contains a more formal treatment. We follow the arrangement of the different functions and subroutines in the standard, but explain directly in the list. For a more detailed treatment we refer to Metcalf and Reid (1990, 1993).
When a parameter below is optional it is given in lower case characters. When an argument list contains several arguments the function can be called either by position related arguments or by a keyword. Keyword must be used if some previous argument is not included. Keywords are normally the names that are given below.
We have not always given all the natural limitations to the variables, for example that the rank is not permitted to be negative.

1. Function which determines if a certain argument is in an actual argument list:

The function PRESENT(A) returns .TRUE. if the argument A is in the calling list, .FALSE. in the other case. The use is illustrated in the example program in chapter 8 of the main text.

2. Numerical functions:

The following are available from Fortran 77: ABS, AIMAG, AINT, ANINT, CMPLX, CONJG, DBLE, DIM, DPROD, INT, MAX, MIN, MOD, NINT, REAL and SIGN. In addition, CEILING, FLOOR and MODULO have been added to Fortran 90. Only the last one is difficult to explain, which is most easily done with the examples from ISO (1991)
    MOD (8,5)    gives  3     MODULO (8,5)    gives  3
    MOD (-8,5)   gives -3     MODULO (-8,5)   gives  2
    MOD (8,-5)   gives  3     MODULO (8,-5)   gives -2
    MOD (-8,-5)  gives -3     MODULO (-8,-5)  gives -3
The following functions from Fortran 77 can use a kind-parameter like in AINT(A, kind), namely AINT, ANINT, CMPLX, INT, NINT and REAL. A historic fact is that the numerical functions in Fortran 66 had to have specific (different) names in different precisions, and these explicit names are still the only ones which can be used when a function name is passed as an argument.
A complete table of all the numerical functions follow. Those names that are indicated with a star * are not permitted to be used as arguments. Some functions, like INT and IFIX have two specific names, either can be used. On the other hand, some functions do not have any specific name. Below I use C for complex floating point values, D for floating point values in double precision, I for integers, and R for floating point values in single precision.

Function        Generic  Specific Data type
                name     name     Arg   Res

Conversion      INT      -        I     I
 to integer            * INT      R     I
                       * IFIX     R     I
                       * IDINT    D     I
 (of the real part)      -        C     I

Conversion      REAL   * REAL     I     R
 to real               * FLOAT    I     R
                         -        R     R
                       * SNGL     D     R
 (real part)             -        C     R

Conversion      DBLE     -        I     D
 to double               -        R     D
 precision               -        D     D
 (real part)             -        C     D

Conversion      CMPLX    -     I (2I)   C
 to complex              -     R (2R)   C
                         -     D (2D)   C
                         -        C     C

Truncation      AINT     AINT     R     R
                         DINT     D     D

Rounding        ANINT    ANINT    R     R
                         DNINT    D     D
                NINT     NINT     R     I
                         IDNINT   D     I

Absolute        ABS      IABS     I     I
 value                   ABS      R     R
                         DABS     D     D
                         CABS     C     R

Remainder       MOD      MOD     2I     I
                         AMOD    2R     R
                         DMOD    2D     D
                MODULO   -       2I     I
                         -       2R     R
                         -       2D     D

Floor           FLOOR    -        I     I
                         -        R     R
                         -        D     D

Ceiling         CEILING  -        I     I
                         -        R     R
                         -        D     D

Transfer        SIGN     ISIGN   2I     I
 of sign                 SIGN    2R     R
                         DSIGN   2D     D

Positive        DIM      IDIM    2I     I
 difference              DIM     2R     R
                         DDIM    2D     D

Inner product   -        DPROD    R     D

Maximum         MAX    * MAX0     I     I
                       * AMAX1    R     R
                       * DMAX1    D     D
                -      * AMAX0    I     R
                -      * MAX1     R     I

Minimum         MIN    * MIN0     I     I
                       * AMIN1    R     R
                       * DMIN1    D     D
                -      * AMIN0    I     R
                -      * MIN1     R     I

Imaginary part  -        AIMAG    C     R

Conjugate       -        CONJG    C     C
Truncation is towards zero, INT(-3.7) becomes -3, but rounding is correct, NINT(-3.7) becomes -4. The new functions FLOOR and CEILING truncate towards minus and plus infinity, respectively. The function CMPLX can have one or two arguments, if two arguments are present these must be of the same type but not COMPLEX.
The function MOD(X,Y) calculates X - INT(X/Y)*Y.
The sign transfer function SIGN(X,Y) takes the sign of the second argument and puts it on the first argument, ABS(X) if Y >= 0 and -ABS(X) if Y < 0.
Positive difference DIM is a function I have never used, but DIM(X,Y) gives X-Y if this is positive and zero in the other case.
Inner product DPROD on the other hand is a very useful function which gives the product of two numbers in single precision as a double precision number. It is both fast and accurate.
The two functions MAX and MIN are unique in that they may have an arbitrary number of arguments, but at least two. The arguments have to be of the same type, but are not permitted to be of type COMPLEX.

3. Mathematical functions:

Same as in Fortran 77. All trigonometric functions work in radians. The following are available: ACOS, ASIN, ATAN, ATAN2, COS, COSH, EXP, LOG, LOG10, SIN, SINH, SQRT, TAN and TANH. A historic fact is that the mathematical functions in Fortran 66 had to have specific (different) names in different precisions, and these explicit names are still the only ones which can be used when a function name is passed as an argument.
A complete table of all the mathematical functions follow. Below I use C for complex floating point values, D for floating point values in double precision, I for integers, and R for floating point values in single precision.

Function        Generic  Specific Data type
                name     name     Arg   Res

Square root     SQRT     SQRT     R     R
                         DSQRT    D     D
                         CSQRT    C     C

Exponential     EXP      EXP      R     R
                         DEXP     D     D
                         CEXP     C     C

Natural         LOG      ALOG     R     R
 logarithm               DLOG     D     D
                         CLOG     C     C

Common          LOG10    ALOG10   R     R
 logarithm               DLOG10   D     D

Sine            SIN      SIN      R     R
                         DSIN     D     D
                         CSIN     C     C

Cosine          COS      COS      R     R
                         DCOS     D     D
                         CCOS     C     C

Tangent         TAN      TAN      R     R
                         DTAN     D     D

Arcsine         ASIN     ASIN     R     R
                         DASIN    D     D

Arccosine       ACOS     ACOS     R     R
                         DACOS    D     D

Arctangent      ATAN     ATAN     R     R
                         DATAN    D     D
                ATAN2    ATAN2   2R     R
                         DATAN2  2D     D

Hyperbolic      SINH     SINH     R     R
 sine                    DSINH    D     D

Hyperbolic      COSH     COSH     R     R
 cosine                  DCOSH    D     D

Hyperbolic       TANH    TANH     R     R
 tangent                 DTANH    D     D
The purpose of most of these functions is obvious. Note that they are all only defined for floating point numbers, and not for integers. You can therefore not calculate the square root of 4 as SQRT(4), but instead you can use NINT(SQRT(REAL(4))). Please also note that all complex functions return the principal value. The square root gives a real result for a real argument in single or double precision, and a complex result for a complex argument. So SQRT(-1.0) gives an error message (usually already at compile time), while you can get the complex square root using the following statements.
COMPLEX, PARAMETER    :: MINUS_ONE = -1.0
COMPLEX               :: Z
Z = SQRT(MINUS_ONE)
The argument for the usual logarithms has to be positive, while the argument for CLOG must be different from zero. The modulus for the argument to ASIN and ACOS has to be at most 1. The result will be within [-pi/2, pi/2] and [0, pi], respectively.
The function ATAN will return a value in [-pi/2, pi/2].
The function ATAN2(Y,X) = arctan(y,x) will return a value in (-pi, pi]. If Y is positive the result will be positive. If Y is zero the result will be zero if X is positive, and pi if X is negative. If Y is negative the result will be negative. If X is zero the result will be plus or minus pi/2. Both X and Y are not permitted to be zero simultaneously. The purpose of the function is to avoid division by zero.
A natural limitation for the mathematical functions is the limited accuracy and range, which means that for example EXP can cause underflow or overflow at rather common values of the argument. The trigonometric functions will get very low accuracy for large arguments. These limitations are implementation dependent, and should be given in the vendor's manual.

4. Character string functions:

The functions below perform operations from and to character strings. Please note that ACHAR works with the standard ASCII character set while CHAR works with the representation in the computer you are using.
ACHAR(I)          Returns the ASCII character which has number I
ADJUSTL(STRING)   Adjusts to the left
ADJUSTR(STRING)   Adjusts to the right
CHAR(I, kind)     Returns the character that has the number I
IACHAR(C)         Returns the ASCII number of the character C
ICHAR(C)          Returns the number of character C

INDEX(STRING, SUBSTRING, back)  Returns the starting position for a
    substring within  a  string.  If BACK  is  true then you get the
    last starting position, in the  other case, the first one.

LEN_TRIM(STRING)  Returns the length of the string without the possibly 
    trailing blanks.

       LGE(STRING_A, STRING_B)
       LGT(STRING-A, STRING_B)
       LLE(STRING_A, STRING_B)
       LLT(STRING_A, STRING_B)
The above routines compare two strings using sorting according to ASCII. If a string is shorter than the other, blanks are added at the end of the short string. If a string contains a character outside the ASCII character set, the result is implementation-dependent.
REPEAT(STRING, NCOPIES)    Concatenates a character string NCOPIES
                           times with itself.
SCAN(STRING, SET, back)    Returns the position of the first occurrence
                           of any character in the string SET in the string
                           STRING. If BACK is true, you will get
                           the rightmost such character.
TRIM(STRING)               Returns the character string STRING without
                           trailing blanks.
VERIFY(STRING, SET, back)  Returns the position of the first character
                           in STRING which is not in SET.  If BACK
                           is TRUE, you get the last one!
                           The result is zero if all characters are
                           included!

5. Character string function for request:

LEN(STRING) returns the length of a character string. There does not have to be assigned a value to the variable STRING.

6. Kind functions:

KIND(X)
SELECTED_INT_KIND(R)
SELECTED_REAL_KIND(p, r)
The first returns the kind of the actual argument, which can be of the type INTEGER, REAL, COMPLEX, LOGICAL or CHARACTER. The argument X does not have to be assigned any value. The second returns an integer kind with the requested number of digits, and the third returns the kind for floating-point numbers with numerical precision at least P digits and one decimal exponent range between -R and +R. The parameters P and R must be scalar integers. At least one of P and R must be given. The result of SELECTED_INT_KIND is an integer from zero and upward, if the desired kind is not available you will get -1. If several implemented types satisfy the condition, the one with the least decimal range is used. If there still are several types or kinds that satisfy the condition, the one with the smallest kind number will be used.
The result of SELECTED_REAL_KIND is also an integer from zero and upward; if the desired kind is not available, then -1 is returned if the precision is not available, -2 if the exponent range is not available and -3 if no one of the requirements are available. If several implemented types satisfy the condition, the one with the least decimal precision is returned, and if there are several of them, the one with the least kind number is returned.
Examples are given in chapter 2 of the main text. Examples of kinds in a few different implementations (NAG and Cray) are given in Appendix 6.

7. Logical function:

LOGICAL(L, kind) converts between different kinds of logical variables. Logical variables can be implemented in various ways, for example with a physical representation occupying one bit (not recommended), one byte, one word or perhaps even one double word. This difference is important if COMMON and EQUIVALENCE with logical variables have been misused in a program in the traditional way of Fortran 66 programming.

8. Numerical inquiry functions:

These functions work with a certain model of integer and floating-point arithmetics, see ISO (1991), section 13.7.1. The functions return properties of numbers of the same kind as the variable X, which can be real and in some cases integer. Functions that return properties of the actual argument X are available in section 12 below, floating-point manipulation functions.
DIGITS(X)       The number of significant digits
EPSILON(X)      The  least  positive  number  that added
                to 1 returns a number that is greater than 1
HUGE(X)         The largest positive number
MAXEXPONENT(X)  The largest exponent
MINEXPONENT     The smallest exponent
PRECISION(X)    The decimal precision
RADIX(X)        The base in the model
RANGE(X)        The decimal exponent
TINY(X)         The smallest positive number

9. Bit inquiry function:

BIT_SIZE(I) returns the number of bits according to the model of bit representation in the standard ISO (1991), section 13.5.7. Normally we get the number of bits in a (whole) word.

10. Bit manipulation functions:

The model for bit representation in the standard ISO (1991), section 13.5.7 is used.
BTEST(I, POS)         .TRUE. if the position number POS of I is 1
IAND(I, J)            logical  addition  of  the  bit characters in
                      variables I and J

IBCLR(I, POS)         puts a zero in the bit in position POS
IBITS(I, POS, LEN)    uses LEN bits of the word I with
                      beginning in position POS,  the additional bits
                      are set to zero.  It requires that 
                      POS + LEN <= BIT_SIZE(I)
IBSET(I, POS)         puts the bit in position POS to 1
IEOR(I, J)            performs logical exclusive OR
IOR(I, J)             performs logical OR
ISHFT(I, SHIFT)       performs logical shift (to the right if the number
                      of steps SHIFT < 0 and to the left if SHIFT > 0).
                      Positions that are vacated are set to zero.
ISHFTC(I, SHIFT, size) performs  logical  shift  a  number  of  steps
                      circularly to   the   right  if  SHIFT  <  0,
                      circularly to the left if SHIFT > 0.  If SIZE
                      is given, it is required that 0 < SIZE <=
                      BIT_SIZE(I).  Shift is only done for the bits
                      that are  in the SIZE rightmost positions, but
                      for all positions if SIZE is not given.
NOT(I)                returns a logical complement

11. Transfer functions:

TRANSFER(SOURCE, MOULD, size) specifies that the physical representation of the first argument SOURCE shall be treated as if it had type and parameters as the second argument MOULD, but without converting it. The purpose is to give a possibility to move a quantity of a certain type via a routine that does not have exactly that data type.

12. Floating-point manipulation functions:

These functions work in a certain model of integer and floating-point arithmetic, see the standard ISO(1991), section 13.7.1. The functions return numbers related to the actual variable X of the type REAL. Functions that return properties for the numbers of the same kind as the variable X are under section 8 (Numerical inquiry functions).
EXPONENT(X)         exponent of the number
FRACTION(X)         the fractional part of the number
NEAREST(X, S)       returns the next representable number in
                    the direction of the sign of S
RRSPACING(X)        returns the inverted value of the distance
                    between the two nearest possible numbers 
SCALE(X, I)         multiplies X by the base to the power I
SET_EXPONENT(X, I)  returns the number that has the fractional
                    part of X and the exponent I
SPACING(X)          the distance between the two nearest
                    possible numbers 

13. Vector- and matrix-multiplication functions:

DOT_PRODUCT(VECTOR_A, VECTOR_B) makes a scalar product of two vectors, which must have the same length (same number of elements).
    Please note that if VECTOR_A is of type COMPLEX the result is SUM(CONJG(VECTOR_A)*VECTOR_B).
MATMUL(MATRIX_A, MATRIX_B) makes the matrix product of two matrices, which must be consistent, i.e. have the dimensions like (M, K) and (K, N). Used in chapter 11 of the main text.

14. Array functions:

ALL(MASK, dim) returns a logical value that indicates whether all relations in MASK are .TRUE., along only the desired dimension if the second argument is given. ANY(MASK, dim) returns a logical value that indicates whether any relation in MASK is .TRUE., along only the desired dimension if the second argument is given.
COUNT(MASK, dim) returns a numerical value that is the number of relations in MASK who are .TRUE., along only the desired dimension if the second argument is given.
MAXVAL(ARRAY, dim, mask) returns the largest value in the array ARRAY, of those that obey the relation in the third argument MASK if that one is given, along only the desired dimension if the second argument DIM is given.
MINVAL(ARRAY, dim, mask) returns the smallest value in the array ARRAY, of those that obey the relation in the third argument MASK if that one is given, along only the desired dimension if the second argument DIM is given.
PRODUCT(ARRAY, dim, mask) returns the product of all the elements in the array ARRAY, of those that obey the relation in the third argument MASK if that one is given, along only the desired dimension if the second argument DIM is given.
SUM (ARRAY, dim, mask) returns the sum of all the elements in the array ARRAY, of those that obey the relation in the third argument MASK if that one is given, along only the desired dimension if the second argument DIM is given. An example is given in Appendix 3, section 10.

15. Array inquiry functions:

See also Appendix 3, section 10.
ALLOCATED(ARRAY) is a logical function which indicates if the array is allocated.
LBOUND(ARRAY, dim) is a function which returns the lower dimension limit for the ARRAY. If DIM (the dimension) is not given as an argument, you get an integer vector, if DIM is included, you get the integer value with exactly that lower dimension limit, for which you asked.
SHAPE(SOURCE) is a function which returns the shape of an array SOURCE as an integer vector.
SIZE(ARRAY, dim) is a function which returns the number of elements in an array ARRAY, if DIM is not given, and the number of elements in the relevant dimension if DIM is included.
UBOUND(ARRAY, dim) is a function similar to LBOUND which returns the upper dimensional limits.

16. Array construct functions:

MERGE(TSOURCE, FSOURCE, MASK) is a function which joins two arrays. It gives the elements in TSOURCE if the condition in MASK is .TRUE. and FSOURCE if the condition in MASK is .FALSE. The two fields TSOURCE and FSOURCE have to be of the same type and the same shape. The result is also of this type and this shape. Also MASK must have the same shape. I here give a rather complete example of the use of MERGE which also uses RESHAPE from the next section in order to build suitable test matrices.
Note that the two subroutines WRITE_ARRAY and WRITE_L_ARRAY are test routines to write matrices which in the first case are of a REAL type, in the second case of a LOGICAL type.
IMPLICIT NONE
INTERFACE
      SUBROUTINE WRITE_ARRAY (A)
             REAL :: A(:,:)
      END SUBROUTINE WRITE_ARRAY
      SUBROUTINE WRITE_L_ARRAY (A)
             LOGICAL :: A(:,:)
      END SUBROUTINE WRITE_L_ARRAY
END INTERFACE

REAL, DIMENSION(2,3)      :: TSOURCE, FSOURCE, RESULT
LOGICAL, DIMENSION(2,3)   :: MASK
TSOURCE = RESHAPE( (/ 11, 21, 12, 22, 13, 23 /), &
                   (/ 2, 3 /) )
FSOURCE = RESHAPE( (/ -11, -21, -12, -22, -13, -23 /), &
                   (/ 2,3 /) )
MASK = RESHAPE( (/ .TRUE., .FALSE., .FALSE., .TRUE., &
                   .FALSE., .FALSE. /), (/ 2,3 /) )

RESULT = MERGE(TSOURCE, FSOURCE, MASK)
CALL WRITE_ARRAY(TSOURCE)
CALL WRITE_ARRAY(FSOURCE)
CALL WRITE_L_ARRAY(MASK)
CALL WRITE_ARRAY(RESULT)
END

SUBROUTINE WRITE_ARRAY (A)
REAL :: A(:,:)
DO I = LBOUND(A,1), UBOUND(A,1)
   WRITE(*,*) (A(I, J), J = LBOUND(A,2), UBOUND(A,2) )
END DO
RETURN
END SUBROUTINE WRITE_ARRAY

SUBROUTINE WRITE_L_ARRAY (A)
LOGICAL :: A(:,:)
DO I = LBOUND(A,1), UBOUND(A,1)
   WRITE(*,"(8L12)") (A(I, J), J= LBOUND(A,2), UBOUND(A,2))
END DO
RETURN
END SUBROUTINE WRITE_L_ARRAY
The following output is obtained
       11.0000000   12.0000000   13.0000000
       21.0000000   22.0000000   23.0000000

       -11.0000000 -12.0000000  -13.0000000
       -21.0000000 -22.0000000  -23.0000000

                 T           F            F
                 F           T            F

       11.0000000  -12.0000000  -13.0000000
      -21.0000000   22.0000000  -23.0000000
PACK(ARRAY, MASK, vector) packs an array to a vector with the control of MASK. The shape of the logical array MASK has to agree with the one for ARRAY or MASK must be a scalar. If VECTOR is included, it has to be an array of rank 1 (i.e. a vector) with at least as many elements as those that are true in MASK and have the same type as ARRAY. If MASK is a scalar with the value .TRUE. then VECTOR instead must have the same number of elements as ARRAY. The result is a vector with as many elements as those in ARRAY that obey the conditions if VECTOR is not included (i.e. all elements if MASK is a scalar with value .TRUE.). In the other case the number of elements of the result will be as many as in VECTOR. The values will be the approved ones, i.e. the values which fulfill the condition, and will be in the ordinary Fortran order. If VECTOR is included and the number of its elements exceeds the number of approved values, the lacking values required for the result are taken from the corresponding locations in VECTOR.
The following example is based on the modification of the one for MERGE , but I give now only the results.
   ARRAY
         11.0000000   12.0000000   13.0000000
         21.0000000   22.0000000   23.0000000

   VECTOR
        -11.0000000
        -21.0000000
        -12.0000000
        -22.0000000
        -13.0000000
        -23.0000000


   MASK
          T               F              F
          F               T              F

   PACK(ARRAY, MASK)
         11.0000000
         22.0000000

   PACK(ARRAY, MASK, VECTOR)
         11.0000000
         22.0000000
        -12.0000000
        -22.0000000
        -13.0000000
        -23.0000000
SPREAD(SOURCE, DIM, NCOPIES) returns an array of the same type as the argument SOURCE with the rank increased by one. The parameters DIM and NCOPIES are integer. If NCOPIES is negative the value zero is used instead. If SOURCE is a scalar, then SPREAD becomes a vector with NCOPIES elements that all have the same value as SOURCE. The parameter DIM indicates which index is to be extended. It has to be within the range 1 and 1+(rank of SOURCE), if SOURCE is a scalar then DIM has to be one. The parameter NCOPIES is the number of elements in the new dimensions. Additional discussion is given in the solution to exercise (11.1). UNPACK(VECTOR, MASK, ARRAY) scatters a vector to an array under control of MASK. The shape of the logical array MASK has to agree with the one for ARRAY. The array VECTOR has to have the rank 1 (i.e. it is a vector) with at least as many elements as those that are true in MASK, and also has to have the same type as ARRAY. If ARRAY is given as a scalar then it is considered to be an array with the same shape as MASK and the same scalar elements everywhere.
The result will be an array with the same shape as MASK and the same type as VECTOR. The values will be those from VECTOR that are accepted (i.e. those fulfilling the condition in MASK), taken in the ordinary Fortran order, while in the remaining positions in ARRAY the old values are kept.

17. ARRAY reshape function.

RESHAPE(SOURCE, SHAPE, pad, order) constructs an array with a specified shape SHAPE starting from the elements in a given array SOURCE. If PAD is not included then the size of SOURCE has to be at least PRODUCT (SHAPE). If PAD is included it has to have the same type as SOURCE. If ORDER is included, it has to be an INTEGER array with the same shape as SHAPE and the values must be a permutation of (1,2,3,...,N), where N is the number of elements in SHAPE , it has to be less than, or equal to 7. The result has of course a shape SHAPE and the elements are those in SOURCE, possibly complemented with PAD. The different dimensions have been permuted at the assignment of the elements if ORDER was included, but without influencing the shape of the result.
A few simple examples are given in the previous and the next section and also in Appendix 3, section 9. A more complicated example, illustrating also the optional arguments, follows.
! PROGRAM TO TEST THE OPTIONAL ARGUMENTS TO RESHAPE
  INTERFACE
     SUBROUTINE WRITE_MATRIX(A)
         REAL, DIMENSION(:,:) :: A
     END SUBROUTINE  WRITE_MATRIX
  END INTERFACE

  REAL, DIMENSION (1:9) :: B = (/ 11, 12, 13, 14, 15, 16, 17, 18, 19 /)
  REAL, DIMENSION (1:3, 1:3) :: C, D, E
  REAL, DIMENSION (1:4, 1:4) :: F, G, H

  INTEGER, DIMENSION (1:2) :: ORDER1 = (/ 1, 2 /)
  INTEGER, DIMENSION (1:2) :: ORDER2 = (/ 2, 1 /)
  REAL, DIMENSION (1:16)   :: PAD1 = (/ -1, -2, -3, -4, -5, -6, -7, -8, &
                                 &   -9, -10, -11, -12, -13, -14, -15, -16 /)

  C = RESHAPE( B, (/ 3, 3 /) )
  CALL WRITE_MATRIX(C)

  D = RESHAPE( B, (/ 3, 3 /), ORDER = ORDER1)
  CALL WRITE_MATRIX(D)

  E = RESHAPE( B, (/ 3, 3 /), ORDER = ORDER2)
  CALL WRITE_MATRIX(E)

  F = RESHAPE( B, (/ 4, 4 /), PAD = PAD1)
  CALL WRITE_MATRIX(F)

  G = RESHAPE( B, (/ 4, 4 /), PAD = PAD1, ORDER = ORDER1)
  CALL WRITE_MATRIX(G)

  H = RESHAPE( B, (/ 4, 4 /), PAD = PAD1, ORDER = ORDER2)
  CALL WRITE_MATRIX(H)

  END

  SUBROUTINE WRITE_MATRIX(A)
  REAL, DIMENSION(:,:) :: A
  WRITE(*,*)
  DO I = LBOUND(A,1), UBOUND(A,1)
     WRITE(*,*) (A(I,J), J = LBOUND(A,2), UBOUND(A,2))
  END DO
  END SUBROUTINE WRITE_MATRIX
The output from the above program is as follows.
  11.0000000  14.0000000  17.0000000
  12.0000000  15.0000000  18.0000000
  13.0000000  16.0000000  19.0000000

  11.0000000  14.0000000  17.0000000
  12.0000000  15.0000000  18.0000000
  13.0000000  16.0000000  19.0000000

  11.0000000  12.0000000  13.0000000
  14.0000000  15.0000000  16.0000000
  17.0000000  18.0000000  19.0000000

  11.0000000  15.0000000  19.0000000  -4.0000000
  12.0000000  16.0000000  -1.0000000  -5.0000000
  13.0000000  17.0000000  -2.0000000  -6.0000000
  14.0000000  18.0000000  -3.0000000  -7.0000000

  11.0000000  15.0000000  19.0000000  -4.0000000
  12.0000000  16.0000000  -1.0000000  -5.0000000
  13.0000000  17.0000000  -2.0000000  -6.0000000
  14.0000000  18.0000000  -3.0000000  -7.0000000

  11.0000000  12.0000000  13.0000000  14.0000000
  15.0000000  16.0000000  17.0000000  18.0000000
  19.0000000  -1.0000000  -2.0000000  -3.0000000
  -4.0000000  -5.0000000  -6.0000000  -7.0000000

18. ARRAY manipulation functions.

The shift functions return the shape of an array unchanged, but move the elements. They are rather difficult to explain so I recommend to study also the standard ISO (1991). CSHIFT(ARRAY, SHIFT, dim) performs circular shift by SHIFT positions to the left if SHIFT is positive and to the right if it is negative. If ARRAY is a vector the shift is being done in a natural way, if it is an array of a higher rank then the shift is in all sections along the dimension DIM. If DIM is missing it is considered to be 1, in other cases it has to be a scalar integer number between 1 and n (where n equals the rank of ARRAY ). The argument SHIFT is a scalar integer or an integer array of rank n-1 and the same shape as the ARRAY, except along the dimension DIM (which is removed because of the lower rank). Different sections can therefore be shifted in various directions and with various numbers of positions.
EOSHIFT(ARRAY, SHIFT, boundary, dim) performs shift to the left if SHIFT is positive and to the right if it is negative. Instead of the elements shifted out new elements are taken from BOUNDARY. If ARRAY is a vector the shift is being done in a natural way, if it is an array of a higher rank, the shift on all sections is along the dimension DIM. If DIM is missing, it is considered to be 1, in other cases it has to have a scalar integer value between 1 and n (where n equals the rank of ARRAY). The argument SHIFT is a scalar integer if ARRAY has rank 1, in the other case it can be a scalar integer or an integer array of rank n-1 and with the same shape as the array ARRAY except along the dimension DIM (which is removed because of the lower rank).
The corresponding applies to BOUNDARY which has to have the same type as the ARRAY. If the parameter BOUNDARY is missing you have the choice of values zero, .FALSE. or blank being used, depending on the data type. Different sections can thus be shifted in various directions and with various numbers of positions. A simple example of the above two functions for the vector case follows, both the program and the output.
REAL, DIMENSION(1:6)  :: A = (/ 11.0, 12.0, 13.0, 14.0, &
                                15.0, 16.0 /)
REAL, DIMENSION(1:6)  :: X, Y
WRITE(*,10) A
X = CSHIFT ( A, SHIFT = 2)
WRITE(*,10) X
Y = CSHIFT (A, SHIFT = -2)
WRITE(*,10) Y
X = EOSHIFT ( A, SHIFT = 2)
WRITE(*,10) X
Y = EOSHIFT ( A, SHIFT = -2)
WRITE(*,10) Y
10  FORMAT(1X,6F6.1)
END

       11.0  12.0  13.0   14.0  15.0  16.0
       13.0  14.0  15.0   16.0  11.0  12.0
       15.0  16.0  11.0   12.0  13.0  14.0
       13.0  14.0  15.0   16.0   0.0   0.0
        0.0   0.0  11.0   12.0  13.0  14.0
A simple example of the above two functions in the matrix case follows. I have here used RESHAPE in order to create a suitable matrix to start work with. The program is not reproduced here, only the main statements.
B = (/ 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 /)

  11.0  12.0  13.0   Z = RESHAPE( B, (/3,3/) )
  14.0  15.0  16.0
  17.0  18.0  19.0

  17.0  18.0  19.0   X = CSHIFT (Z, SHIFT = 2)
  11.0  12.0  13.0
  14.0  15.0  16.0

  13.0  11.0  12.0   X = CSHIFT ( Z, SHIFT = 2, DIM = 2)
  16.0  14.0  15.0
  19.0  17.0  18.0

  14.0  15.0  16.0   X = CSHIFT (Z, SHIFT = -2)
  17.0  18.0  19.0
  11.0  12.0  13.0

  17.0  18.0  19.0   X = EOSHIFT ( Z, SHIFT = 2)
   0.0   0.0   0.0
   0.0   0.0   0.0

  13.0   0.0   0.0   X = EOSHIFT ( Z, SHIFT = 2, DIM = 2)
  16.0   0.0   0.0
  19.0   0.0   0.0

   0.0   0.0   0.0   X = EOSHIFT ( Z, SHIFT = -2)
   0.0   0.0   0.0
  11.0  12.0  13.0
TRANSPOSE (MATRIX) transposes a matrix, which is an array of rank 2. It replaces the rows and columns in the matrix.

19. Array location functions:

MAXLOC(ARRAY, mask) returns the position of the greatest element in the array ARRAY, if MASK is included only for those which fulfill the conditions in MASK. The result is an integer vector! It is used in the solution of exercise (11.1). MINLOC(ARRAY, mask) returns the position of the smallest element in the array ARRAY , if MASK is included only for those which fulfill the conditions in MASK. The result is an integer vector!

20. Pointer inquiry functions:

ASSOCIATED(POINTER, target) is logical function that indicates if the pointer POINTER is associated with some target, and if a specific TARGET is included it indicates if it is associated with exactly that target. If both POINTER and TARGET are pointers, the result is .TRUE. only if both are associated with the same target. I refer the reader to chapter 12 of the main text, Pointers.

21. Intrinsic subroutines:

  • Time routines:

    DATE_AND_TIME(date, time, zone, values)
    
    A subroutine which returns the date, the time and the time zone. At least one argument has to be given. DATE must be a scalar character string variable with at least 8 characters and it is assigned the value CCYYMMDD for century, year, month and day. All are given numerically, with blanks if the system does not include the date.
    TIME must also be a scalar character string variable with at least 10 characters and it is assigned a value hhmmss.sss for time in hours, minutes, seconds and milliseconds. All are given numerically with blanks if the system does not include a clock.
    ZONE must be a scalar character string variable with at least 5 characters and it is assigned the value +hhmm for sign, time in hours and minutes for the local time difference with UTC (which was previously called Greenwich Mean Time). All are given numerically, with blanks if the system does not include a clock. In Sweden we therefore get +0100 in winter and +0200 in summer, in Novosibirsk we get +0700 .
    The variable VALUES is instead an integer vector with at least 8 elements, it gives the easiest way of using the results from DATE_AND_TIME at the calculations in a program. If the system does not include the date or the time you get the value -HUGE(0), that is the smallest integer number in the model, as output. The vector will include the following elements: year, month, day, time difference in minutes, hours, minutes, seconds and milliseconds.
    SYSTEM_CLOCK(COUNT, COUNT_RATE, COUNT_MAX)
    
    Subroutine which returns the system time. At least one argument has to be given. COUNT is a scalar integer which is increased by one for each cycle up to COUNT_MAX , where it starts once again. If there is no system clock then -HUGE(0) is returned. COUNT_RATE is a scalar integer that gives the number of cycles per second. If there is no system clock the value zero is returned.
    COUNT_MAX is a scalar integer which gives the maximum value that COUNT can reach. If there is no system clock, zero is returned instead.
  • Bit copy routine:

    MVBITS(FROM, FROMPOS, LEN, TO, TOPOS)
    
    A subroutine which copies the sequence of bits in position FROMPOS and has the length LEN to target TO starting in position TOPOS. The remaining bits are not changed. All quantities have to be integers and all except TO have to have INTENT(IN) while TO is supposed to have INTENT(INOUT) and be of the same kind type as FROM. The same variable can be both FROM and TO. Some natural restrictions apply to the values of LEN, FROMPOS and TOPOS and you also have to consider the value of BIT_SIZE.
  • Random number routines:

    A sequence of pseudo random numbers can be generated from a starting value which is stored as an integer vector. The subroutines offer a portable interface towards an implementation dependent random number sequence.
    RANDOM_NUMBER(HARVEST)
    
    This subroutine returns in the floating-point number variable HARVEST one (or several if HARVEST is an array) random numbers between zero and 1.
    RANDOM_SEED(size, put, get)
    
    This subroutine resets, or gives information about, the random number generator. No arguments have to be provided. The output variable SIZE must be a scalar integer and gives the number of integers (N) the processor uses for the starting value. The input variable PUT is an integer vector which puts the starting numbers provided by the user into the random number generator. The output variable GET (also an integer vector)reads the present starting value. Example:
    CALL RANDOM_SEED                    ! Initializing
    CALL RANDOM SEED (SIZE=K)           ! Sets K = N
    CALL RANDOM_SEED (PUT = SEED (1:K)) ! Uses the starting value
                                        !     given by the user
    CALL RANDOM_SEED (GET = OLD(1:K))   ! Returns  the  present
                                        !     starting value
    
    A simple example on the use of these functions is now available.


Last modified: August 10, 2009
boein@nsc.liu.se