= Open Boundary modules in NEMO: OBC/BDY merge = Last edited [[Timestamp]] [[PageOutline]] As part of the 2011 workplan, it is planned to merge the OBC and BDY modules to provide a single module to do one-way nesting in NEMO. This page outlines the design for the new module. It is intended as a discussion document. Please feel free to add comments. == Introduction == Blah == Summary of main features == * The following algorithms will be included in the first implementation: * Clamped and Flow Relaxation Scheme. (Clamped is FRS with rimwidth=1). * Flather radiation condition on barotropic solution. * NPO version of Orlanski radiation condition as currently included in OBC. Plan to code ''implicit'' time-stepping for greater stability and to avoid OBC restarts. May also code normal, and fully 2D Orlanski condition. * "Mercator-style" barotropic boundary conditions. * Tidal harmonic forcing (included in Flather boundary condition). * There will be two ways of specifying the boundary geometry: a. Using obc_par.h90 to define straight-line segments. One will be able to define more than one segment for each of east, west, south, north boundaries. b. Reading in the list of points from the data file as is now done in BDY. * The low-level code will use the BDY-style specification of the boundary geometry (an unstructured list of gridpoints). If obc_par.h90 is used then this will be converted to BDY-style arrays in the initialisation. * The read of external boundary data will be handled by fldread.F90 as is done for the SBC fields. This is clean and flexible. In the future this will permit online interpolation of boundary data. * It will be possible to define more than one open boundary set. This will allow different boundary conditions to be applied on different boundaries. == Control and coding structure == The namelist for the new module would look like this: {{{ !----------------------------------------------------------------------- &namobc ! one-way open boundaries ("key_obc") !----------------------------------------------------------------------- nb_obc = 2 ! Number of open boundary sets cn_mask = '' ! name of mask file (ln_mask=T) nn_dyn = 1, 0, ! Choice of schemes for velocities nn_tra = 1, 1, ! Choice of schemes for T and S nn_barotropic = 1, 0, ! Choice of schemes for barotropic solution nn_ice_lim2 = 0, 0, ! Choice of schemes for ice (LIM2) ln_vol = .false.,.false., ! total volume correction (see volbdy parameter) ln_mask = .false.,.false., ! boundary mask from filbdy_mask (T), boundaries are on edges of domain (F) ln_tides = .false.,.false., ! Apply tidal harmonic forcing with Flather condition nn_rimwidth = 9, 1, ! width of the relaxation zone nn_dtactl = 1, 1, ! = 0, bdy data are equal to the initial state ! = 1, bdy data are read in 'bdydata .nc' files nn_volctl = 0, 0, ! = 0, the total water flux across open boundaries is zero ! = 1, the total volume of the system is conserved / !----------------------------------------------------------------------- &namobc_dta ! one-way open boundaries ("key_obc") !----------------------------------------------------------------------- ! ! file name ! frequency (hours) ! variable ! time interp. ! clim ! 'daily'/ ! weights ! rotation ! ! ! ! (if <0 months) ! name ! (logical) ! (T/F) ! 'monthly' ! filename ! pairing ! bn_tem = 'obcdta_grid_T' , 24 , 'votemper', .true. , .false., 'daily' , '' , '' bn_sal = 'obcdta_grid_T' , 24 , 'vosaline', .true. , .false., 'daily' , '' , '' bn_uvel = 'obcdta_grid_U' , 24 , 'vozocrtx', .true. , .false., 'daily' , '' , '' bn_vvel = 'obcdta_grid_V' , 24 , 'vomecrty', .true. , .false., 'daily' , '' , '' bn_ssh = 'obcdta_bt_grid_T' , 6 , 'sossheig', .true. , .false., 'daily' , '' , '' bn_ubar = 'obcdta_bt_grid_U' , 6 , 'vozocrtx', .true. , .false., 'daily' , '' , '' bn_vbar = 'obcdta_bt_grid_V' , 6 , 'vomecrty', .true. , .false., 'daily' , '' , '' cn_dir = './obcdta' ! root directory for the location of the boundary data files / !----------------------------------------------------------------------- &namobc_dta ! one-way open boundaries ("key_obc") !----------------------------------------------------------------------- ! ! file name ! frequency (hours) ! variable ! time interp. ! clim ! 'daily'/ ! weights ! rotation ! ! ! ! (if <0 months) ! name ! (logical) ! (T/F) ! 'monthly' ! filename ! pairing ! bn_tem = 'obcdta_clim_grid_T' , -1 , 'votemper', .true. , .true., 'yearly' , '' , '' bn_sal = 'obcdta_clim_grid_T' , -1 , 'vosaline', .true. , .true., 'yearly' , '' , '' cn_dir = './obcdta' ! root directory for the location of the boundary data files / }}} It is possible to define more than one open boundary set in case you want to use different boundary conditions for different boundaries. For instance one might want to apply different algorithms on the east and west boundaries of a domain, or one might want to apply boundary conditions from an external model over part of the open boundary but climatological boundary conditions over another part of the open boundary (as in the example above). For each open boundary set you define which conditions to apply to each set of variables using '''nn_dyn''', '''nn_tra''' etc. For example: * '''nn_tra''' = 0 : Apply no boundary condition (land boundary) * '''nn_tra''' = 1 : Clamped/relaxation boundary condition * '''nn_tra''' = 2 : Normal radiation condition * '''nn_tra''' = 3 : NPO radiation condition * etc. There is a separate '''&namobc_dta''' namelist for each boundary set, which defines the input data files using the '''FLD''' structure from fldread.F90. (This will allow for online interpolation of boundary conditions in the future). For each set of variables there is a module which applies the boundary conditions each timestep, eg. for T and S you have '''obctra.F90''' which looks like this: {{{ MODULE obctra CONTAINS SUBROUTINE obc_tra( kt ) DO ib_set = 1, nb_set SELECT CASE ( nn_tra(ib_set) ) CASE(0) CYCLE CASE(1) CALL obc_tra_frs( kt, ib_set ) CASE(2) CALL obc_tra_rad( kt, ib_set ) END SELECT END DO END SUBROUTINE SUBROUTINE obc_tra_frs( kt, ib_set ) ... }}} The module to read in the boundary data from files would be rewritten to use fldread.F90. For each boundary stream a '''TYPE FLD''' structure array would be constructed depending on which fields need to be read in. We can merge the obc_dta and obc_dta_bt routines by making the barotropic subloop counter '''jit''' an optional argument. {{{ MODULE obcdta USE fldread INTEGER, PARAMETER :: nb_dta_max = 10 TYPE(FLD), ALLOCATABLE, DIMENSION(:,:) :: bf CONTAINS SUBROUTINE obc_dta( kt, jit ) INTEGER :: kt ! time step index INTEGER, OPTIONAL :: jit ! barotropic subloop index TYPE(FLD_N), ALLOCATABLE, DIMENSION(:,:) :: blf_i ALLOCATE( bf (nb_stream, nb_dta_max), STAT=ierror ) ALLOCATE( blf_i(nb_stream, nb_dta_max), STAT=ierror ) DO ib_stream = 1, nb_stream IF( kt == nit000 ) THEN zcount = 0 ! nn_barotropic must come first IF( nn_barotropic .gt. 0 ) THEN ! set up information for SSH zcount = zcount + 1 ALLOCATE( bf(ib_stream,zcount)%fnow(jpib,jpjb,1) ) IF( ln_tint(ib_stream) ) ALLOCATE( bf(ib_stream,zcount)%fdta(jpib,jpjb,1,2) ) blf_i(ib_stream,zcount)%clname = cn_dta(ib_stream)//"_grid_T.nc" ... ! set up information for U zcount = zcount + 1 ... ! set up information for V zcount = zcount + 1 ENDIF IF ( nn_tra .gt. 0 ) THEN ! set up information for T and S ... ENDIF .... nn_dta(ib_stream) = zcount CALL fld_fill( bf(ib_stream,1:nn_dta(ib_stream)), blf_i(ib_stream,1:nn_dta(ib_stream)), ... ) ENDIF ! kt == nit000 IF( PRESENT(jit) && nn_barotropic(ib_stream) .gt. 0 ) THEN ! Update barotropic boundary conditions only ! jit is optional argument for fld_read CALL fld_read( kt, jit, nn_fobc, bf(ib_stream, 1:3) ) ELSE CALL fld_read( kt, nn_fobc, bf(ib_stream, 1:nb_dta(ib_stream) ) ENDIF ! ! Update internal boundary data arrays from bf%fnow ! END DO ! ib_stream END SUBROUTINE }}}