Difference between revisions of "Frequently Asked Questions"

From WikiROMS
Jump to navigationJump to search
(→‎Compiling and Linking: compile-time errors)   (change visibility)
Line 15: Line 15:


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.
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.
=== Errors at compile time ===
First of all, read the error messages from the compiler carefully to see if you can figure out what they are talking about. There are several classes of errors (add more as you see them):
* Syntax errors in the fortran: check the intermediate .f90 file for the exact code at the line numbers in the report.
* Trouble with the netcdf module file: was it created with the same version of the same compiler? If not, there could be trouble. I've seen gfortran give a cryptic message about expecting a left parenthesis when faced with a module file from an older version of gfortran.
* Trouble with other modules: one instance of this is due to incorrect dependency information in MakeDepend. The ROMS code must be compiled in the correct order and failure to do so might give something like:
<div class="box">cd Build; ifort -c  bc_2d.f90
fortcom: Error: bc_2d.f90, line 30: Error in opening the Library module file.<br />[MOD_PARAM]<br />    USE mod_param<br />----------^<br />fortcom: Error: bc_2d.f90, line 32: Error in opening the Library module file.</div>
Here, it failed to compile mod_param.F before bc_2d.F, leading to trouble. I was recently reminded that the '--objdir=$(SCRATCH_DIR)' option in MDEPFLAGS is not optional.


=== Errors at link time ===
=== Errors at link time ===

Revision as of 18:48, 20 October 2009

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 &
    or to run in parallel on a shared-memory machine:
    setenv OMP_THREAD_NUM 2
    oceanO < ROMS/External/ocean_upwelling.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 or OMP_THREAD_NUM=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.

Errors at compile time

First of all, read the error messages from the compiler carefully to see if you can figure out what they are talking about. There are several classes of errors (add more as you see them):

  • Syntax errors in the fortran: check the intermediate .f90 file for the exact code at the line numbers in the report.
  • Trouble with the netcdf module file: was it created with the same version of the same compiler? If not, there could be trouble. I've seen gfortran give a cryptic message about expecting a left parenthesis when faced with a module file from an older version of gfortran.
  • Trouble with other modules: one instance of this is due to incorrect dependency information in MakeDepend. The ROMS code must be compiled in the correct order and failure to do so might give something like:
cd Build; ifort -c bc_2d.f90 fortcom: Error: bc_2d.f90, line 30: Error in opening the Library module file.
[MOD_PARAM]
USE mod_param
----------^
fortcom: Error: bc_2d.f90, line 32: Error in opening the Library module file.

Here, it failed to compile mod_param.F before bc_2d.F, leading to trouble. I was recently reminded that the '--objdir=$(SCRATCH_DIR)' option in MDEPFLAGS is not optional.

Errors at link time

One common problem is that differing options were used when compiling libraries vs. the ROMS code proper. For instance, you get a message about:

crash.f90:(.text+0x19): undefined reference to 'nf_close__'

when you know you linked to the netcdf library. You can query the library to see what it has:

nm libnetcdf.a | grep nf_close

0000000000000e60 T nf_close_
U nf_close_

Clearly, there's a mismatch in the number of underscores which is preventing it from linking successfully. See if you can find a fortran option for controlling the number of underscores and try to match how the library was compiled. Otherwise, you can recompile the library to match how you compile ROMS.

Basic Usage

What are the ways that ROMS can receive the wind and other surface forcing?

  1. One option is to provide the stresses and fluxes via analytic expressions in ana_smflux.h and ana_stflux.h.
  2. One option is to provide analytic expressions for the winds and other atmospheric fields in ana_winds.h and friends, and define BULK_FLUXES.
  3. ROMS can also read fields from NetCDF files, also stresses or winds, depending on the state of BULK_FLUXES. These can be provided as:
    1. Point measurements, in which ROMS will rotate to the correct directions from East (u) and North (v).
    2. Gridded fields on the ROMS grid, in which case the directions have to match the directions on your grid.
    3. Gridded fields on a larger, usually coarser grid. These are in East and North, with ROMS doing the rotation. ROMS picks up its cue on whether to interpolate+rotate or not based on the grid dimensions of these fields. If the dimensions exactly match that of your own grid, ROMS will assume that it is on your grid. If you plan on using global fields of dimension 180x90, say, don't build a grid with those dimensions.

What are the ways that ROMS can receive tides on the boundaries?

  1. You can specify a time-dependent boundary condition file that temporally resolves the tides and skip the tides file entirely.
  2. You can specify SSH_TIDES and/or UV_TIDES and provide a tides file and skip the boundary condition file entirely - though this option might require you to tell ROMS in globaldefs.h that you really, really don't need an OBC_FILE. Usual practice is to provide both surface elevation and currents in the tidal file and to use FSCHAPMAN and M2FLATHER on the open sides of your domain.
  3. You can specify other 2-d currents and surface elevation signals as coming in, plus have tides and use the ADD_M2OBC and ADD_FSOBC options.

How can I set up passive tracers?

You need to #define T_PASSIVE to get passive tracers. The flag ANA_PASSIVE determines whether or not the initial conditions are analytic (from ana_passive.h) or from the initial condition file. As for boundary conditions, all tracers have either analytic boundary conditions or they all come from the same boundary condition file. If you need to read values from a file, the field names are dye_01, dye_02, etc. I successfully set up a uniform dye_01 using ANA_PASSIVE with boundary conditions from a file. The boundary file has u,v,T,S for many times and (analytic) biological values for the beginning and end times. I have a script to read one biology value, change the attributes and the value to my uniform value, then write it into the boundary file with the name dye_01_west, etc. I then had to edit varinfo.dat to reflect that it's using bio_time rather than ocean_time.

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.