Introduction

TRACMASS can read in various variables, such as different levels of velocity field resolution and tracer variables like temperature and salinity. The user has high flexibility available when it comes to input data reading. However, the process is not straightforward, thus, a short guide is presented here in hopes to clear up some of the confusion.

In this chapter, we will illustrate the basics of file reading and the general logic behind it. This chapter is mainly written for the setup of read_field.F90, but the methods are the same for setup_grid.F90 (and kill_zones.F90). All of these files are located in the project folder (read more about the project folder here). Furthermore, instead of writing the algorithm yourself from scratch, it is recommended to use one of the provided files and modify it to your needs. This way you will save time and your sanity.

Note:
It is recommended to use the read_field.F90 file as a template for reading in the necessary data, by finding a file that best fits your project's needs and modifying it where necessary.

Structure of read_field.F90

The function to read in variables is called every global time iteration. In general, the file can be split up in two parts: data reading into TRACMASS, and data transformation/processing so that the data fits TRACMASS' framework. An example of this is velocity field data on an Arakawa A-grid. TRACMASS carries out its calculations with data distributed on an Arakawa C-grid, thus, to accurately run the simulation, it is necessary to transform the dataset from Arakawa A-grid to C-grid. As every dataset will differ, there is no standardized method for reading in the data from global climate model simulations. Thus, you will most likely need to modify some of the data for TRACMASS to work with it in the read_field.F90 file.

This is a list of variables that are mandatory to be populated:

  • uflux - volume/mass flux through a grid face in the x direction
  • vflux - same as uflux but in the y direction
  • dzt - size of the vertical wall computed at T points.
This is the bare minimum data needed in the read_field.F90 file for calculating trajectories.

Note:
The file read_field.F90 is called every global time step and at the very top of the file, subroutine swap_time() is called, which handles the velocity and tracer field time stepping for you.

Reading in velocity fields

Even though the horizontal velocity (or flux fields) are mandatory, the subgrid level data for these fields are optional. Thus, ueul_name and veul_name must be defined, while the other ones can be left empty or completely omitted from the namelist file. An example of setting up the namelist for TRACMASS to read in the velocity field is the following:

&INIT_GRID_DESCRIPTION
       !   Direction of the grid (1 - E->W, S->N, B->U)
       griddir = 1,1,-1

       !   Does the netcdf data start with a zero index?
       zeroindx = .FALSE.

       !   Directory of physical data (u,v,T,S,MLD,etc)
       physDataDir    = '',
       !   Physical data file prefix         
       physPrefixForm = 'ORCA1-N406_',
       !   Date format for physical data
       dateformat     = 'YYYYMMDD'
       !   Name of Tgrid, Ugrid and Vgrid
       tGridName      = '',
       uGridName      = '',
       vGridName      = '',

       !   Suffix of files, e.g. ".nc"
       fileSuffix     = '.nc',

       !   Variable names in the physical data file
       !   Sea surface height
       hs_name        = 'sossheig'
       !   Name of resolved zonal (u) velocity and
       !   ------//------ meridional (v) velocity
       ueul_name      = 'vozocrtx',
       veul_name      = 'vomecrty',

       !   Name of eddy induced zonal (u) velocity
       !   -----//----- meridional (v) velocity
       usgs_name      = 'vozoeivu', 
       vsgs_name      = 'vomeeivv',

       !   Name of secondary subgrid zonal (u) velocity
       !   -----//----- meridional (v) velocity
       usub_name       = '',
       vsub_name       = '',
/

In this example, we have our velocity data saved in the same file as our tracers, thus, the tGridName, uGridName, and vGridName fields have been left blank. In this case, these variables could have been completely omitted.

Here we have also defined the location of our file, the various parts of the file format to merge it together, and finally, start the process of reading in the files. For this, there are two functions that you will use: get2DfieldNC() and get3DfieldNC(). As can be seen, both have the same inputs.

get2DfieldNC(fieldFile ,varName, start2D, count2D, stcase)

get3DfieldNC(fieldFile ,varName, start3D, count3D, stcase)

  • fieldFile - file name with the path to the file
  • varName - variable name that will be read in from the file
  • start2D/start3D - the starting index for reading the file in four dimensions [x, y, z, t]
  • count2D/count3D - the number of indexes to read in four dimensions [x, y, z, t]
  • stcase - the storage format of the array (refer to the documentation)

This is how the code would look in our read_field.F90 file. In this case, we read in the whole spatial domain and only one timestep, specifically the first time step, as our `.nc` file starts with index=1.

! Create a prefix that is used for the date formatting.
dateprefix = filledFileName(dateFormat, currYear, currMon, currDay)

! Create a path to the file from which the data will be read
fieldFile = TRIM(physDataDir)//TRIM(physPrefixForm)//TRIM(dateprefix)//TRIM(fileSuffix)

! Call a function that reads 'ueul_name' from the defined file and saved it in array 'uvel'
uvel(1:imt,1:jmt,1:km) = get3DfieldNC(fieldFile, ueul_name, [imindom,jmindom,1,1], [imt,jmt,km,1], 'st')

! And do the same for the zonal velocity field. 
vvel(1:imt,1:jmt,1:km) = get3DfieldNC(fieldFile, veul_name, [imindom,jmindom,1,1], [imt,jmt,km,1], 'st')

There is high flexibility in the frequency of reading in data, thus great care should be taken to ensure the read_field.F90 file algorithm matches the time stepping definition in the namelist file of the global time step.

Reading tracers

Reading in tracer data is essentially the same as the velocity field data, and it is recommended to use the code for tracer reading found in project NEMO. Every iter iteration, the file reads in the next dataset or computes it. If reading from a file is necessary, the code checks if the dataset is 2D or 3D and reads the corresponding shape into the file. Finally, the dataset is saved in the correct timestep and can be used for future calculations.

 !! Tracers
 IF (l_tracers) THEN
   ! Go throgh the tracers
   DO itrac = 1, numtracers
     ...
     ...
     ...
   END DO    
 END IF

Next, it is necessary to understand the frequency of the general loop and also the time resolution of the tracer dataset itself. For example, if we have velocity field data with 15-minute resolution, we might want to read it in every 15 minutes, while a tracer, such as temperature, might only have hourly resolution. For this purpose, it is useful to use variables, such as currYear, currMon, currDay, currHour, currMin, currSec. For example, this is how the syntax would look conceptually:

 !! Tracers
 IF (l_tracers) THEN
   ! Check if we are on the hour (10:00, 14:00, 00:00, etc...):
   IF (currMin .EQ. 0) THEN
     ! Go throgh the tracers
     DO itrac = 1, numtracers
       ! Read in or compute the tracers
       ...
       ...
     END DO    
   END IF
 END IF

If you would like to learn how to set up a custom tracer, check out this tutorial -> Add a Custom Tracer.