If you are using
Navigator 4.x
or
Internet Explorer 4.x
or
Omni Web 4.x
, this site will not render
correctly!
gfdl's home page > people > John Dunne >
Adding SiO4 to the MOM4 OCMIP2_BIOTIC package
This HOWTO describes in detail the process of adding a tracer to MOM4,
starting with ocmip2_biotic, assuming that you are already versed in
running
existing tracers in MOM4. Silicate is used as an example case.
The basic idea is to:
1) Copy an existing module to a new name
2) Go through the code looking for lines dealing with phosphate, copying them directly below, and changing them to silicate
3) Add the new module to ocean_tpm.F90
4) create new input files
5) Point the runscript to the new forcing, module and input files
1) Copy an existing module to a new name
2) Go through the code looking for lines dealing with phosphate, copying them directly below, and changing them to silicate
3) Add the new module to ocean_tpm.F90
4) create new input files
5) Point the runscript to the new forcing, module and input files
1) Copy an existing module to a new name
Assuming that you have gone through the HOWTO for running the ocmip2_biotic code in MOM4, go to the directory in which the tracer code resides, copy the existing ocmip2_biotic.F90 module to a new name, and open this file in a text editor:
cd ~/jakarta/om1_ocmip2_biotic/src/mom4/ocean_tracers/
cp ocmip2_biotic.F90 ocmip2_biotic_si.F90
emacs ocmip2_biotic_si.F90
First, browse through this file, noticing that it contains a list of the external modules that it uses and then the subroutines contained within it:
-
public :: ocmip2_biotic_bbc - calculate
bottom boundary conditions at each time step
public :: ocmip2_biotic_end - wrap things up and do integral calculations at the end
public :: ocmip2_biotic_init - initialize arrays at the beginning
public :: ocmip2_biotic_sbc - calculate surface boundary conditions at each time step
public :: ocmip2_biotic_set_up - Set up infrastructure and options for prognostic and diagnostic tracers
public :: ocmip2_biotic_source - calculate interior source terms at each time step
public :: ocmip2_biotic_start - set values of constants and arrays, check some things and and do integral calculations at the beginning
public :: ocmip2_biotic_tracercalculate virtual fluxes at each time step
-
private :: allocate_arrays - allocate
arrays used in the module
private :: bc_interp - do time interpolations for boundary conditions at each time step
private :: locate - finds the index of a monotonic array closest to the input value
private :: read_c14atm - read temporal history of atmospheric C-14
private :: read_co2atm - read temporal history of atmospheric CO2
private :: set_array - sets values in a defined part of an array
2) go through the code looking for lines dealing with phosphate, copying them directly below, and changing them to silicate.
Edit biotic_type to add:
-
real :: si_remin_depth
logical :: do_sio4_virtual_flux
real, pointer, dimension(:,:) :: flux_si => NULL()
real, pointer, dimension(:,:,:) :: fsi => NULL()
integer :: id_flux_si = -1
integer :: id_fsi = -1
integer :: id_jprod_si = -1
integer :: id_jsio4 = -1
integer :: id_vstf_sio4 = -1
integer :: ind_sio4
real, pointer, dimension(:,:,:) :: jprod_si => NULL()
real, pointer, dimension(:,:,:) :: jsio4 => NULL()
real :: sio4_global = 0.0
real :: sio4_global_wrk = 0.0
real, pointer, dimension(:,:) :: vstf_sio4 => NULL()
real, pointer, dimension(:) :: zfsi => NULL()
-
character*128 :: sio4_star_file
integer :: sio4_star_id
character*32 :: sio4_star_name
real, allocatable, dimension(:,:,:) :: sio4_star_t
-
allocate( sio4_star_t(isd:ied,jsd:jed,nk) )
sio4_star_t(:,:,:) = 0.0
if (biotic(n)%do_sio4_virtual_flux) then !{
- allocate( biotic(n)%vstf_sio4(isc:iec,jsc:jec) )
- nullify(biotic(n)%vstf_sio4)
allocate( biotic(n)%zfsi(nk) )
allocate( biotic(n)%jprod_si(isc:iec,jsc:jec,nk) )
allocate( biotic(n)%jsio4(isc:iec,jsc:jec,nk) )
allocate( biotic(n)%fsi(isc:iec,jsc:jec,nk) )
allocate( biotic(n)%flux_si(isc:iec,jsc:jec) )
biotic(n)%jprod_si(:,:,:) = 0.0
biotic(n)%jsio4(:,:,:) = 0.0
biotic(n)%fsi(:,:,:) = 0.0
if (biotic(n)%do_sio4_virtual_flux) then !{
- biotic(n)%vstf_sio4(:,:) = 0.0
-
real :: total_silicate
total_silicate = 0.0
total_silicate = total_silicate + &
-
t_prog(biotic(n)%ind_sio4)%field(i,j,k,taup1) * &
grid%dat(i,j) * grid%tmask(i,j,k) * grid%dht(i,j,k)
call mpp_sum(total_silicate)
write (stdout(), &
-
'(/'' Total silicate = '',es19.12,'' Gmol-Si'')')&
-
total_silicate * 1.0e-09
biotic(n)%do_sio4_virtual_flux .or. &
if (biotic(n)%do_sio4_virtual_flux) then !{
-
call write_data(biotic(n)%file_out, &
-
'sio4_global_wrk', biotic(n)%sio4_global_wrk)
-
'sio4_global', biotic(n)%sio4_global)
biotic(n)%do_sio4_virtual_flux .or. &
if (biotic(n)%do_sio4_virtual_flux) then !{
-
write (stdout(),'(1x,a,es16.9,a,a)') &
-
'Annual, global, surface mean SiO4 = ', &
biotic(n)%sio4_global, ' (mol/m^3) for instance ', &
trim(biotic(n)%name)
-
if (biotic(n)%do_sio4_virtual_flux) then !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
T_prog(biotic(n)%ind_sio4)%tpme(i,j) = &
-
T_prog(biotic(n)%ind_sio4)%field(i,j,1,tau)
-
T_prog(biotic(n)%ind_sio4)%field(i,j,1,tau)
if (biotic(n)%do_sio4_virtual_flux) then !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%vstf_sio4(i,j) = &
-
t_prog(indsal)%stf(i,j) * &
biotic(n)%sio4_global / biotic(n)%sal_global
-
biotic(n)%vstf_sio4(i,j)
-
!
! SiO4
!
biotic(n)%ind_sio4 = set_prog_tracer('sio4' // suffix, package_name, &
-
longname = 'Silicate' // '(' // trim(name) // ')', &
units = 'mol/m^3', flux_units = 'mol/m^2/s')
-
ind_sio4 = biotic(n)%ind_sio4
call time_interp_external(sio4_star_id, time%model_time, sio4_star_t)
ind_sio4 = biotic(n)%ind_sio4
!
! compute SiO4 restoring term and correct for partial
! production in the bottom box
!
do k = 1, km_c !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
if (t_prog(ind_sio4)%field(i,j,k,taum1) .gt. &
-
sio4_star_t(i,j,k)) then !{
biotic(n)%jprod_sio4(i,j,k) = &
-
(t_prog(ind_sio4)%field(i,j,k,taum1) - &
sio4_star_t(i,j,k)) * &
biotic(n)%r_bio_tau * grid%tmask(i,j,k)
-
biotic(n)%jprod_sio4(i,j,k) = 0.0
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%jprod_sio4(i,j,km_c) = &
-
biotic(n)%jprod_sio4(i,j,km_c) * &
biotic(n)%comp_depth_frac(i,j)
!
!-----------------------------------------------------------------------
! Silicon flux
!-----------------------------------------------------------------------
!
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%flux_si(i,j) = (1.0 - biotic(n)%sigma) * &
-
biotic(n)%jprod_si(i,j,1) * grid%dht(1)
do k = 2, km_c !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%flux_si(i,j) = biotic(n)%flux_si(i,j) + &
-
(1.0 - biotic(n)%sigma) * biotic(n)%jprod_si(i,j,k) * &
grid%dht(k)
!
! calculate the flux at the base of each layer below the
! compensation depth
!
do k = km_c, nk !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%fsi(i,j,k) = biotic(n)%flux_si(i,j) * &
-
biotic(n)%zfsi(k) * grid%tmask(i,j,k)
!
! calculate the dissolution of SiO2 below the compensation
! depth
!
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%jsi(i,j,km_c) = biotic(n)%jsi(i,j,km_c) + &
-
(biotic(n)%flux_si(i,j) * grid%tmask(i,j,km_c) - &
biotic(n)%fsi(i,j,km_c) * grid%tmask(i,j,km_c+1)) / &
grid%dht(km_c)
do k = km_c + 1, nk - 1 !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%jsi(i,j,k) = &
-
(biotic(n)%fsi(i,j,k-1) * grid%tmask(i,j,k) - &
biotic(n)%fsi(i,j,k) * grid%tmask(i,j,k+1)) / grid%dht(k)
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%jsi(i,j,nk) = biotic(n)%fsi(i,j,nk-1) * &
-
grid%tmask(i,j,nk) / grid%dht(nk)
!
!-----------------------------------------------------------------------
! SiO4
!-----------------------------------------------------------------------
!
do k = 1, km_c !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%jsio4(i,j,k) = -biotic(n)%jprod_si(i,j,k)
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%jsio4(i,j,km_c) = biotic(n)%jsio4(i,j,km_c) + &
-
(biotic(n)%flux_si(i,j) * grid%tmask(i,j,km_c) - &
biotic(n)%fsi(i,j,km_c) * grid%tmask(i,j,km_c+1)) / &
grid%dht(km_c)
do k = km_c + 1, nk - 1 !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%jsio4(i,j,k) = &
-
(biotic(n)%fsi(i,j,k-1) * grid%tmask(i,j,k) - &
biotic(n)%fsi(i,j,k) * grid%tmask(i,j,k+1)) / &
grid%dht(k)
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%jsio4(i,j,nk) = &
-
biotic(n)%fsi(i,j,nk-1) * grid%tmask(i,j,nk) / &
grid%dht(nk)
do k = 1, nk !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
t_prog(ind_sio4)%source(i,j,k) = &
-
t_prog(ind_sio4)%source(i,j,k) + biotic(n)%jsio4(i,j,k)
if (biotic(n)%id_flux_si .gt. 0) then
-
used = send_data(biotic(n)%id_flux_si, &
-
biotic(n)%flux_si(isc:iec,jsc:jec), &
time%model_time, rmask = grid%tmask(isc:iec,jsc:jec,1))
if (biotic(n)%do_sio4_virtual_flux) then !{
-
if (biotic(n)%id_vstf_sio4 .gt. 0) then
-
used = send_data(biotic(n)%id_vstf_sio4, &
-
biotic(n)%vstf_sio4(isc:iec,jsc:jec), &
time%model_time, rmask = grid%tmask(isc:iec,jsc:jec,1))
if (biotic(n)%id_jprod_si .gt. 0) then
-
used = send_data(biotic(n)%id_jprod_si, &
-
biotic(n)%jprod_si(isc:iec,jsc:jec,:), &
time%model_time, rmask = grid%tmask(isc:iec,jsc:jec,:))
if (biotic(n)%id_jsio4 .gt. 0) then
-
used = send_data(biotic(n)%id_jsio4, &
-
biotic(n)%jsio4(isc:iec,jsc:jec,:), &
time%model_time, rmask = grid%tmask(isc:iec,jsc:jec,:))
if (biotic(n)%id_fsi .gt. 0) then
-
used = send_data(biotic(n)%id_fsi, &
-
biotic(n)%fsi(isc:iec,jsc:jec,:), &
time%model_time, rmask = grid%tmask(isc:iec,jsc:jec,:))
-
real :: si_remin_depth
real :: sio4_global
-
sio4_star_file, sio4_star_name, &
-
si_remin_depth
sio4_global
-
sio4_star_file = 'sio4_star_ocmip2.nc'
sio4_star_name = 'sio4_star'
!
!-----------------------------------------------------------------------
! Open up the SiO4 file for restoring
!-----------------------------------------------------------------------
!
sio4_star_id = init_external_field(sio4_star_file, &
-
sio4_star_name, &
domain = Domain%domain2d)
-
call mpp_error(FATAL, &
-
trim(sub_name) // &
': Error: could not open sio4_star file: ' // &
trim(sio4_star_file))
si_remin_depth = 1000.0
sio4_global = 91.7 * rho_avg * 1.0e-06 ! mol/m^3
biotic(index)%si_remin_depth = si_remin_depth
biotic(index)%sio4_global = sio4_global
biotic(n)%zfsi(k) = &
-
exp(-(grid%zw(k) - &
-
biotic(n)%compensation_depth) / biotic(n)%si_remin_depth)
call read_data(biotic(n)%file_in, &
-
'sio4_global', biotic(n)%sio4_global, &
domain=Domain%domain2d, timelevel=1)
-
'sio4_global_wrk', biotic(n)%sio4_global_wrk, &
domain=Domain%domain2d, timelevel=1)
write (stdout(),'(1x,a,es16.9,a,a)') & 'Annual, global, surface mean SiO4 = ', &
biotic(n)%sio4_global, ' (mol/m^3) for instance ', &
trim(biotic(n)%name)
if (biotic(n)%do_sio4_virtual_flux) then !{
-
biotic(n)%id_vstf_sio4 = register_diag_field('ocean_model',&
-
'vstf_sio4'//str, grid%tracer_axes(1:2), &
Time%model_time, 'Virtual SiO4 flux', ' ', &
missing_value = -1.0e+10)
biotic(n)%id_flux_si = register_diag_field('ocean_model', &
-
'flux_si'//str, grid%tracer_axes(1:2), &
Time%model_time, 'Si flux', ' ', &
missing_value = -1.0e+10)
biotic(n)%id_jprod_si = register_diag_field('ocean_model', &
-
'jprod_si'//str, grid%tracer_axes(1:3), &
Time%model_time, 'Restoring Si production', ' ', &
missing_value = -1.0e+10)
biotic(n)%id_jsio4 = register_diag_field('ocean_model', &
-
'jsio4'//str, grid%tracer_axes(1:3), &
Time%model_time, 'SiO4 source', ' ', &
missing_value = -1.0e+10)
biotic(n)%id_fsi = register_diag_field('ocean_model', &
-
'fsi'//str, grid%tracer_axes(1:3), &
Time%model_time, 'Si change', ' ', &
missing_value = -1.0e+10)
-
real :: total_silicate
biotic(n)%do_sio4_virtual_flux .or. &
if (biotic(n)%do_sio4_virtual_flux) then !{
-
do j = jsc, jec !{
-
do i = isc, iec !{
-
biotic(n)%sio4_global_wrk = biotic(n)%sio4_global_wrk + &
-
t_prog(biotic(n)%ind_sio4)%field(i,j,1,tau) * &
grid%tmask(i,j,1) * grid%dat(i,j) * dtts
biotic(n)%do_sio4_virtual_flux .or. &
if (biotic(n)%do_sio4_virtual_flux) then !{
-
call mpp_sum(biotic(n)%sio4_global_wrk)
biotic(n)%do_sio4_virtual_flux .or. &
if (biotic(n)%do_sio4_virtual_flux) then !{
-
biotic(n)%sio4_global = biotic(n)%sio4_global_wrk / &
-
biotic(n)%global_wrk_duration / grid%tcella(1)
biotic(n)%do_sio4_virtual_flux .or. &
if (biotic(n)%do_sio4_virtual_flux) then !{
-
biotic(n)%sio4_global_wrk = 0.0
Edit ~/jakarta/ocmip2_biotic/src/mom4/ocean_core/ocean_tpm.F90 to add the appropriate lines for ocmip2_biotic_si corresponding to existing lines for ocmip2_biotic:
-
use ocmip2_biotic_si_mod
if (do_ocmip2_biotic_si) then !{
-
call ocmip2_biotic_si_bbc
if (do_ocmip2_biotic_si) then !{
-
call ocmip2_biotic_si_end
!
! Biotic with Si
!
call ocmip2_biotic_si_init
if (do_ocmip2_biotic_si) then !{
-
call ocmip2_biotic_si_sbc(robert)
call ocmip2_biotic_si_set_up
if (do_ocmip2_biotic_si) then !{
-
call ocmip2_biotic_si_source
if (do_ocmip2_biotic_si) then !{
-
call ocmip2_biotic_si_start
if (do_ocmip2_biotic_si) then !{
-
call ocmip2_biotic_si_tracer
MOM4 must be feed initial and boundary conditions on the model grid in COARDS-compliant netCDF format. For a detailed explanation of preprocessing tools available to create these files, see the MOM4 guide, or follow the Preprocessing guidelines for creation of silicate boundary condition. Briefly, some helpful commands are given below:
Make an input_fields directory in your path (depending on the size of the files, you may need to put this in your /archive... /home is limited to 10 GBytes).
In order to regrid a data field, the preprocessing routine must be fed an input field that has values at all points contained within the model grid - i.e. extrapolated over land and spanning the X, Y, and Z grids. To extrapolate a field in ferret, qlogin to the analysis cluster (AC) and follow these ferret commands:
-
use woa01_silicate_monthly_smooth.nc
use woa01_silicate_annual.nc
show data/full
LET silicate_full=if (z[g=silicate[d=2]] lt 80) then silicate[d=1,gz=GDP1] else silicate[d=2,gz=GDP1,l=1]
let sio4=extrap(silicate_full,500,0.001,0.6)/1000
SET MEMORY/SIZE=100
save/file="woa01_sio4_monthly_om2_extrap.nc"/CLOBBER sio4
-
/home/[USERNAME]/jakarta/om1_ocmip2_biotic/src/preprocessing/regrid_3d/regrid_3d.csh
-
set output_dir = /preprocessing/regrid_3d
set src_file = /archive/fms/mom4/input_data/levitus_ewg.nc
set dest_grid = /home/z1l/mom4_data_set/test3/grid_orig.nc
set dest_file = regrid_3d
-
numfields = 2
src_field_name = 'temp', 'salt'
In the AC, run the shell script simply by:
cd /home/[USERNAME]/jakarta/om1_ocmip2_biotic/src/preprocessing/regrid_3d/
regrid_3d.csh
If you need to further edit the netCDF file in order to conform to formatting requirements, you may want to edit the file. To do this, you must first dump the file to ascii format and then probably (if it's big) separate the file into parts after finding out how many lines there are:
ncdump woa01_sio4_om1_bc.nc > woa01_sio4_om1_bc.cdl
wc -l woa01_sio4_om1_bc.cdl
head --lines=12630 woa01_sio4_om1_bc.cdl > woa01_sio4_om1_bc.head
tail --lines=2699284 woa01_sio4_om1_bc.cdl > woa01_sio4_om1_bc.tail
-
netcdf woa01_sio4_om1_bc {
dimensions:
-
grid_x_T = 96 ;
grid_y_T = 40 ;
zt = 24 ;
TIME = UNLIMITED ; // (12 currently)
-
float grid_x_T(grid_x_T) ;
-
grid_x_T:cartesian_axis = "X" ;
grid_x_T:units = "degree_east" ;
-
grid_y_T:cartesian_axis = "Y" ;
grid_y_T:units = "degree_north" ;
-
zt:long_name = "zt" ;
zt:units = "meters" ;
zt:cartesian_axis = "z" ;
zt:positive = "down" ;
-
TIME:units = "seconds since 0000-01-01 00:00:00" ;
TIME:time_origin = "01-JAN-0000 00:00:00" ;
TIME:modulo = "T" ;
-
x_T:long_name = "noname" ;
x_T:units = "nounits" ;
-
y_T:long_name = "noname" ;
y_T:units = "nounits" ;
-
sio4:long_name = "World Ocean Atlas 2001 Silicate" ;
sio4:units = "mol SiO4 m-3" ;
cat woa01_sio4_om1_bc.head.head woa01_sio4_om1_bc.tail > woa01_sio4_om1_bc.cdl
ncgen -o woa01_sio4_om2_bc_173.nc woa01_sio4_om1_bc.cdl
Create a new experiment in your jakarta_tracers.xml file called om1_ocmip2_biotic_si, and change all of the tracer-related information:
Make the new ocean_tpm.F90 and ocmip2_biotic_si.F90 files part of the suite of files copied into the source directory tree and linked with the Makefile by adding the lines:
/bin/cp ~/jakarta/om1_ocmip2_biotic/src/mom4/ocean_core/ocean_tpm.F90 mom4/ocean_tracers
/bin/cp ~/jakarta/om1_ocmip2_biotic/src/mom4/ocean_tracers/ocmip2_biotic_si.F90 mom4/ocean_tracers
-
<diagTable file="/home/[USERNAME]/jakarta/input/diag_table_biotic_si"/>
-
"ocean_model","sio4","sio4","ocean_biotic_sc","all",.true.,"none",2
"ocean_model","jsio4","jsio4","ocean_biotic_3d","all",.true.,"none",2
-
set tracerData = ( /archive/jpd/postinchon/input_fields/ocmip/ocmip_fice_om1_bc.nc /home/jpd/postinchon/input_fields/ocmip/ocmip_po4_om1_bc.nc /home/[USERNAME}/input_fields/woa01_sio4_om1_bc.nc /archive/jpd/postinchon/input_fields/ocmip/ocmip_press_om2_bc.nc /archive/jpd/postinchon/input_fields/ocmip/ocmip_xkw_om1_bc.nc )
-
if ( ) then
-
set tracerNML = ( /home/[USERNAME]/jakarta/input/ocmip2_biotic_si_glob.nml /home/[USERNAME]/jakarta/input/ocmip2_biotic_si.nml )
set tracerTreeTable = ( /home/[USERNAME]/jakarta/input/ocean_tracer_tree /home/[USERNAME]/jakarta/input/ocean_tracer_tree_ob_si )
set tracerTreeInit = ( /home/[USERNAME]/jakarta/input/ocean_tracer_tree_init_ob_si )
-
set tracerNML = ( /home/[USERNAME]/jakarta/input/ocmip2_biotic_si_glob.nml /home/[USERNAME]/jakarta/input/ocmip2_biotic_si_res.nml )
set tracerTreeTable = ( /home/[USERNAME]/jakarta/input/ocean_tracer_tree_res )
set tracerTreeInit = ( /home/[USERNAME]/jakarta/input/ocean_tracer_tree_init_ob_si_res )
