Frequently Asked Questions: Difference between revisions

From WikiROMS
Jump to navigationJump to search
Line 13: Line 13:


== Compiling and Linking ==
== Compiling and Linking ==
The compiling and linking information is all in [[Compiling and Linking]], [[makefile]], and [[build Script]]. Please let us know if any of this is unclear.


== Basic Usage ==
== Basic Usage ==

Revision as of 23:34, 8 July 2008

Frequently Asked Questions

Installation and Configuration

My build finished with no errors. Where is the ROMS executable?

It is either in oceanS (serial), oceanO (shared-memory, OpenMP), oceanM (distributed-memory, MPI), or oceanG (debug). Check the makefile to see which options are on. The makefile definition BINDIR controls where to write the compiled ROMS executable.

What do I have to do to run an application?

There are basically two modes to run a ROMS application: serial or parallel

  1. Mostly all canned applications that come with the ROMS distribution do not need input NetCDF files. The grid, initial conditions and forcing conditions are specified with analytical expressions in Functionals. Any of these test cases can be run by editing the ROMS_APPLICATION definition in the makefile or the build Script. A list of all pre-defined model applications can be found in header file cppdefs.h. The next step is to compile and link using the make tool and, if you are lucky, the program will build. It is good practice to execute make clean first. Then, the application should be run in serial with the command:
    oceanS < ocean_APPLICATION.in > & log &
    where APPLICATION is the lowercase of any of the CPP options defining a distributed test case. For example, the upwelling (UPWELLING) test case uses the input script ocean_upwelling.in which is located in the ROMS/External directory.
  2. A few canned applications that come with ROMS require input NetCDF files which are located in the Data/ROMS directories. Same as above, but if you want run in parallel on a distributed-memory computer use:
    mpirun -np 2 oceanM ocean_test_head.in > & log &
    for the test headland case, for example. You need to be sure that the product of NtileI and NtileJ in ocean_test_head.in is 2 since the above command specifies two processors to run (-np 2). Notice that to compile the model in distributed-memory, you need to edit the makefile (or build Script) and activate USE_MPI. Also, if you use MPICH rather than a native MPI library, define USE_MPIF90 as well. The MPICH library uses a script called mpif90 for compiling.

Compiling and Linking

The compiling and linking information is all in Compiling and Linking, makefile, and build Script. Please let us know if any of this is unclear.

Basic Usage

Algorithm Design

Why the _r8 at the end of real constants?

Some computers use 32 bits for single precision real numbers and 64 bits for double precision, and some use 64 and 128, respectively. For consistent results on various machines, ROMS takes advantage of the intrinsic F90/95 function SELECTED_REAL_KIND( ). See ROMS/Modules/mod_kinds.F. This allows you to associate an integer parameter with a specific data type...in this case r8 is associated with 64-bit precision. RTFM (Read the Fortran90 Manual), or better yet, chapter 11 in Chapman, 2004.

Input/Output NetCDF files

How to add a new variable to ROMS output files?

This question has been asked several times. ROMS IO design is very flexible and easy to expand. There are several steps that need to be followed to add new variables to any of the output files:

  1. The ROMS output NetCDF files are defined by any the routines with the prefix def_ in the ROMS/Utilities directory. For example, in def_his.F a variable can be defined in the history file by just adding:
    IF (Hout(idUvel,ng)) THEN
    Vinfo( 1)=Vname(1,idUvel)
    Vinfo( 2)=Vname(2,idUvel)
    Vinfo( 3)=Vname(3,idUvel)
    Vinfo(14)=Vname(4,idUvel)
    Vinfo(16)=Vname(1,idtime)
    # if defined WRITE_WATER && defined MASKING
    Vinfo(20)='mask_u'
    # endif
    Vinfo(22)='coordinates'
    Aval(5)=REAL(Iinfo(1,idUvel,ng),r8)
    status=def_var(ncHISid(ng),hisVid(idUvel,ng),NF_FOUT, &
    & nvd4,u3dgrd,Aval,Vinfo,ncname)
    END IF
    Correspondingly, the field time records are written in routines with the prefix wrt_. For example, a field can be written in wrt_his.F as:
    IF (Hout(idUvel,ng)) THEN
    scale=1.0_r8
    gtype=gfactor*u3dvar
    status=nf_fwrite3d(ng, iNLM, ncHISid(ng), hisVid(idUvel,ng), &
    & tHISindx(ng), gtype, &
    & LBi, UBi, LBj, UBj, 1, N(ng), scale, &
    # ifdef MASKING
    & GRID(ng) % umask(LBi,LBj), &
    # endif
    & OCEAN(ng) % u(LBi,LBj,1,NOUT))
    IF (status.ne.nf90_noerr) THEN
    IF (Master) THEN
    WRITE (stdout,10) TRIM(Vname(1,idUvel)), tHISindx(ng)
    END IF
    exit_flag=3
    ioerror=status
    RETURN
    END IF
    Ass you may noticed, some knowledge of ROMS internal structure is required to define a new field. Please follow any of output fields examples in such files to define and write the new field.
  2. Notice that ROMS state variables are defined on a horizontal, staggered Arakawa C-grid. In addition, the variables are also staggered in the vertical. Therefore, you need choose the appropriate identifier flag:
    • p2dvar: 2D field at ψ-points
    • r2dvar: 2D field at ρ-points
    • u2dvar: 2D field at u-points
    • v2dvar: 2D field at v-points
    • p3dvar: 3D field at ψ-points
    • r3dvar: 3D field at ρ-points
    • u3dvar: 3D field at u-points
    • v3dvar: 3D field at v-points
    • w3dvar: 3D field at w-points
    • b3dvar: 3D bed-sediment field
  3. Select a unique six-character, case sensitive, field identifier which is defined in file ROMS/Modules/mod_ncparam.F. Notice that all the identifiers are defined in alphabetic order to facilitate the search. Choose a meaningfull identifier prefixed by id. This indentifier needs to be assigned in routine initialize_ncparam during the reading of variable metadata form file varinfo.dat. You need to add code similar to:
    CASE ('idUvel')
    idUvel=varid
    Check the example above to see how the idUvel identifier is used in the internal field metadata arrays.
  4. Define new field metadata in file ROMS/External/varinfo.dat. Follow the examples to define the following field information:
    • Field variable name string. This is the variable name in the output NetCDF file. You need to choose a unique and meaninful variable name.
    • Field long-name string. This is the variable long_name attribute in the output NetCDF file.
    • Field units string. This is the variable units attribute in the output NetCDF file.
    • Field type string. This is the variable field attribute in the output NetCDF file.
    • Associated time-variable name string. This is the variable time attribute in the output NetCDF file.
    • Field identifier string. This is the field six-character unique index used in information arrays.
    • Field staggered C-grid variable type. Use one of flags defined above.
    • Field scale floating-point value. This value is only used in input data to scale field to model units, if necessary. Otherwise, use a unity value.
      Notice that all string information above is specified within single quotes to facilitate free-format reading in mod_ncparam.F. For example:
      'u'  ! Input/Output
      'u-momentum component'
      'meter second-1'  ! [m/s]
      'u-velocity, scalar, series'
      'ocean_time'
      'idUvel'
      'u3dvar'
      1.0d0
  5. Add logical switch Hout(id....) in input script ocean.in to activate the processing of the new field. For example:
    Hout(idUvel) == T  ! 3D U-velocity
    This new switch needs to be read in file ROMS/Utility/inp_par.F, routine read_PhyPar. For example:
    ELSE IF (TRIM(KeyWord).eq.'Hout(idUvel)') THEN
    IF (idUvel.eq.0) THEN
    WRITE (out,280) 'idUvel'
    STOP
    END IF
    Npts=load_l(Nval, Cval, Ngrids, Hout(idUvel,1))
    It is also a good idea to report the new logical switch to standard output. For example:
    IF (Hout(idUvel,ng)) WRITE (out,170) Hout(idUvel,ng), &
    & 'Hout(idUvel)', &
    & 'Write out 3D U-momentum component.'
  6. Follow the same steps to process time-averaged fields. In addition, you need to define, allocate, and initialize in ROMS/Modules/mod_average.F the new ROMS variable used to accumulate the time records. For example:
    real(r8), pointer :: avgu3d(:,:,:)
    ...
    allocate ( AVERAGE(ng) % avgu3d(LBi:UBi,LBj:UBj,N(ng)) )
    ...
    AVERAGE(ng) % avgv3d(i,j,k) = IniVal
    The time-averaged fields are computed in ROMS/Nonlinear/set_avg.F. Check this file to see how this is done.