Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Time varying open boundary conditions for CICE #21

Merged
merged 6 commits into from
Nov 11, 2019
Merged

Time varying open boundary conditions for CICE #21

merged 6 commits into from
Nov 11, 2019

Conversation

jostbr
Copy link
Contributor

@jostbr jostbr commented Nov 11, 2019

Description of changes

Pedro Duarte's (NPI) implementation

This pull request consists of a set of commits to integrate the code written by Pedro Duarte (Norwegian Polar Institute) for time varying open boundary conditions in CICE. While CICE has the ice_restoring.F90 file with the ice_HaloRestore subroutine, this only provide the "hooks" for an open boundary condition treatment, e.g. there were no support for reading data in from an external file and applying these to the boundaries. During his work at NPI on the project "Ecosystem modelling of the Arctic Ocean around Svalbard financed by the Fram Centre flagship Arctic Ocean between 2014 and 2018", Pedro Duarte made use of the above mentioned "hooks" and wrote an implementation for time-varying open boundary conditions. His method revolves around imposing values from e.g an external model by restoring values along the outermost edge of points in the domain to data read in from an input file. A rough outline of the main steps performed by his code are as follows (see commits for details):

  • Initialization related calls, variable declarations and namelist handling in CICE_InitMod.F90, ice_init.F90, ice_domain.F90 and boundary array initializations in subroutine init_forcing_bry in ice_forcing.F90
  • For every time step:
    • Read in daily boundary data from file and scatter to all MPI processes (using existing CICE scattering routines) through subroutines ice_read_nc_bry_2D, ice_read_nc_bry_3D, ice_read_nc_bry_4D in ice_read_write.F90
    • Compute interpolation coefficients using the pre-existing subroutine interp_coeff in ice_forcing.F90
    • Interpolate to time step in subroutines interpolate_data_n and interpolate_data_n_layer in ice_forcing.F90
    • Restore state variables to time-interpolated boundary data in subroutine ice_HaleRestore in ice_restoring.F90

Supplementary changes by MET Norway

In addition to Pedro's code above, other smaller changes have been done by Nicholas Szapiro (MET Norway) and Jostein Brændshøi (MET Norway) for minor adjustments to the boundary treatment. They include (see commits for details):

  • Use first physical point in restore-nudging ice_HaloRestore
  • Restore dynamical variables uvel, vvel, divu, shear, strength to neighbor point in ice_HaloRestore
  • Extrapolate additional grid variables to halo cells in ice_grid.F90
  • Remove zeroing out of halo cells in ice_boundary.F90
  • Calling ice_HaloRestore also before dynamics in CICE_RunMod.F90 (this effectively halves the restoring time scale trestore in ice_in as a side effect)

Instructions on how to use the code

Stuff that needs to be done both when using and not using OBC:

Add the flags
sea_ice_time_bry = .true./.false.
sea_ice_bry_dir = '/path/to/directory/with/boundary_file/' (final '/' important)
to the &domain_nml and &forcing_nml namelist sections, respectively, in your ice_in file. The path sea_ice_bry_dir may be an empty string when sea_ice_time_bry = .false.

The input boundary file

The boundary file needs to contain values for all variables that are required at the boundary by the current boundary implementation. That means aicen, vicen, vsnon, Tsfc, alvln, vlvln_bry, apondn, hpondn, ipondn, iage, Tinz, Sinz all should be present on the file. There is one variable per boundary (see the below example for details on the naming convention). Additionally, the file must contain the dimensions nkice, days, ice_types, eta_t, xi_t (where each of the variables depend on the dimensions as shown below).

Create the CICE boundary file for your simulation, e.g. by using metroms/tools/cice_bry.py or some other tool. Name the file BRY_<YEAR>.nc, so if your run is in 2019, the file is BRY_2019.nc. The way it works now, your boundary file needs to contain entries for all 365 days of the year (dimension days should have length of a full year) even if you only run for a few days of the year. In practice this means you need to fill (e.g. zeros) the file with 365 or 366 (regular or leap) time entries and fill in with your actual boundary data on the time indices that matches the days you have data for and/or want to run for. The code then fetches the correct indices based on the day of the year in model run. The tool metroms/tools/cice_bry.py handles this. If your run extends over one or more year transitions, e.g. you run from 2018 into 2019, you need to split up the boundary data into two files, i.e. BRY_2018.nc and BRY_2019.nc with the first file containing data for the days in 2018 and the second for the days in 2019. The tool metroms/tools/cice_bry.py will handle this very soon.

Below follows an example of a boundary file and the variables it should include as made by metroms/tools/cice_bry.py. As of now, the variables hbrine and fbrine are not used in the code so they may be filled with arbitrary values.

netcdf BRY_2019 {
dimensions:
	nkice = 7 ;
	days = UNLIMITED ; // (365 currently)
	ice_types = 5 ;
	eta_t = 949 ;
	xi_t = 739 ;
variables:
	short Ice_layers(nkice) ;
		Ice_layers:long_name = "vertical ice levels" ;
		Ice_layers:units = "1" ;
	double Sinz_E_bry(days, ice_types, nkice, eta_t) ;
		Sinz_E_bry:long_name = "vertical salinity profile - Eastern boundary" ;
	double Sinz_N_bry(days, ice_types, nkice, xi_t) ;
		Sinz_N_bry:long_name = "vertical salinity profile - Northern boundary" ;
	double Sinz_S_bry(days, ice_types, nkice, xi_t) ;
		Sinz_S_bry:long_name = "vertical salinity profile - Southern boundary" ;
	double Sinz_W_bry(days, ice_types, nkice, eta_t) ;
		Sinz_W_bry:long_name = "vertical salinity profile - Western boundary" ;
	double TLAT_E(eta_t) ;
		TLAT_E:long_name = "T grid center latitude - Eastern boundary" ;
		TLAT_E:units = "degrees_north" ;
	double TLAT_N(xi_t) ;
		TLAT_N:long_name = "T grid center latitude - Northern boundary" ;
		TLAT_N:units = "degrees_north" ;
	double TLAT_S(xi_t) ;
		TLAT_S:long_name = "T grid center latitude - Southern boundary" ;
		TLAT_S:units = "degrees_north" ;
	double TLAT_W(eta_t) ;
		TLAT_W:long_name = "T grid center latitude - Western boundary" ;
		TLAT_W:units = "degrees_north" ;
	double TLON_E(eta_t) ;
		TLON_E:long_name = "T grid center longitude - Eastern boundary" ;
		TLON_E:units = "degrees_east" ;
	double TLON_N(xi_t) ;
		TLON_N:long_name = "T grid center longitude - Northern boundary" ;
		TLON_N:units = "degrees_east" ;
	double TLON_S(xi_t) ;
		TLON_S:long_name = "T grid center longitude - Southern boundary" ;
		TLON_S:units = "degrees_east" ;
	double TLON_W(eta_t) ;
		TLON_W:long_name = "T grid center longitude - Western boundary" ;
		TLON_W:units = "degrees_east" ;
	short Time(days) ;
		Time:long_name = "model time" ;
		Time:units = "days since 2019-01-01 00:00:00" ;
	double Tinz_E_bry(days, ice_types, nkice, eta_t) ;
		Tinz_E_bry:long_name = "vertical temperature profile - Eastern boundary" ;
	double Tinz_N_bry(days, ice_types, nkice, xi_t) ;
		Tinz_N_bry:long_name = "vertical temperature profile - Northern boundary" ;
	double Tinz_S_bry(days, ice_types, nkice, xi_t) ;
		Tinz_S_bry:long_name = "vertical temperature profile - Southern boundary" ;
	double Tinz_W_bry(days, ice_types, nkice, eta_t) ;
		Tinz_W_bry:long_name = "vertical temperature profile - Western boundary" ;
	double Tsfc_E_bry(days, ice_types, eta_t) ;
		Tsfc_E_bry:long_name = "snow/ice surface temperature - Eastern boundary" ;
	double Tsfc_N_bry(days, ice_types, xi_t) ;
		Tsfc_N_bry:long_name = "snow/ice surface temperature - Northern boundary" ;
	double Tsfc_S_bry(days, ice_types, xi_t) ;
		Tsfc_S_bry:long_name = "snow/ice surface temperature - Southern boundary" ;
	double Tsfc_W_bry(days, ice_types, eta_t) ;
		Tsfc_W_bry:long_name = "snow/ice surface temperature - Western boundary" ;
	double aicen_E_bry(days, ice_types, eta_t) ;
		aicen_E_bry:long_name = "ice area (aggregate) - Eastern boundary" ;
	double aicen_N_bry(days, ice_types, xi_t) ;
		aicen_N_bry:long_name = "ice area (aggregate) - Northern boundary" ;
	double aicen_S_bry(days, ice_types, xi_t) ;
		aicen_S_bry:long_name = "ice area (aggregate) - Southern boundary" ;
	double aicen_W_bry(days, ice_types, eta_t) ;
		aicen_W_bry:long_name = "ice area (aggregate) - Western boundary" ;
	double alvln_E_bry(days, ice_types, eta_t) ;
		alvln_E_bry:long_name = "concentration of level ice - Eastern boundary" ;
		alvln_E_bry:units = "1" ;
	double alvln_N_bry(days, ice_types, xi_t) ;
		alvln_N_bry:long_name = "concentration of level ice - Northern boundary" ;
		alvln_N_bry:units = "1" ;
	double alvln_S_bry(days, ice_types, xi_t) ;
		alvln_S_bry:long_name = "concentration of level ice - Southern boundary" ;
		alvln_S_bry:units = "1" ;
	double alvln_W_bry(days, ice_types, eta_t) ;
		alvln_W_bry:long_name = "concentration of level ice - Western boundary" ;
		alvln_W_bry:units = "1" ;
	double apondn_E_bry(days, ice_types, eta_t) ;
		apondn_E_bry:long_name = "melt pond fraction - Eastern boundary" ;
		apondn_E_bry:units = "1" ;
	double apondn_N_bry(days, ice_types, xi_t) ;
		apondn_N_bry:long_name = "melt pond fraction - Northern boundary" ;
		apondn_N_bry:units = "1" ;
	double apondn_S_bry(days, ice_types, xi_t) ;
		apondn_S_bry:long_name = "melt pond fraction - Southern boundary" ;
		apondn_S_bry:units = "1" ;
	double apondn_W_bry(days, ice_types, eta_t) ;
		apondn_W_bry:long_name = "melt pond fraction - Western boundary" ;
		apondn_W_bry:units = "1" ;
	double fbrine_E_bry(days, ice_types, eta_t) ;
		fbrine_E_bry:long_name = "ratio of brine tracer height to ice thickness - Eastern boundary" ;
		fbrine_E_bry:units = "1" ;
	double fbrine_N_bry(days, ice_types, xi_t) ;
		fbrine_N_bry:long_name = "ratio of brine tracer height to ice thickness - Northern boundary" ;
		fbrine_N_bry:units = "1" ;
	double fbrine_S_bry(days, ice_types, xi_t) ;
		fbrine_S_bry:long_name = "ratio of brine tracer height to ice thickness - Southern boundary" ;
		fbrine_S_bry:units = "1" ;
	double fbrine_W_bry(days, ice_types, eta_t) ;
		fbrine_W_bry:long_name = "ratio of brine tracer height to ice thickness - Western boundary" ;
		fbrine_W_bry:units = "1" ;
	double hbrine_E_bry(days, ice_types, eta_t) ;
		hbrine_E_bry:long_name = "brine surface height above sea ice base - Eastern boundary" ;
		hbrine_E_bry:units = "m" ;
	double hbrine_N_bry(days, ice_types, xi_t) ;
		hbrine_N_bry:long_name = "brine surface height above sea ice base - Northern boundary" ;
		hbrine_N_bry:units = "m" ;
	double hbrine_S_bry(days, ice_types, xi_t) ;
		hbrine_S_bry:long_name = "brine surface height above sea ice base - Southern boundary" ;
		hbrine_S_bry:units = "m" ;
	double hbrine_W_bry(days, ice_types, eta_t) ;
		hbrine_W_bry:long_name = "brine surface height above sea ice base - Western boundary" ;
		hbrine_W_bry:units = "m" ;
	double hpondn_E_bry(days, ice_types, eta_t) ;
		hpondn_E_bry:long_name = "mean melt pond depth - Eastern boundary" ;
		hpondn_E_bry:units = "m" ;
	double hpondn_N_bry(days, ice_types, xi_t) ;
		hpondn_N_bry:long_name = "mean melt pond depth - Northern boundary" ;
		hpondn_N_bry:units = "m" ;
	double hpondn_S_bry(days, ice_types, xi_t) ;
		hpondn_S_bry:long_name = "mean melt pond depth - Southern boundary" ;
		hpondn_S_bry:units = "m" ;
	double hpondn_W_bry(days, ice_types, eta_t) ;
		hpondn_W_bry:long_name = "mean melt pond depth - Western boundary" ;
		hpondn_W_bry:units = "m" ;
	double iage_E_bry(days, eta_t) ;
		iage_E_bry:long_name = "ice age - Eastern boundary" ;
	double iage_N_bry(days, xi_t) ;
		iage_N_bry:long_name = "ice age - Northern boundary" ;
	double iage_S_bry(days, xi_t) ;
		iage_S_bry:long_name = "ice age - Southern boundary" ;
	double iage_W_bry(days, eta_t) ;
		iage_W_bry:long_name = "ice age - Western boundary" ;
	double ipondn_E_bry(days, ice_types, eta_t) ;
		ipondn_E_bry:long_name = "mean melt pond ice thickness - Eastern boundary" ;
		ipondn_E_bry:units = "m" ;
	double ipondn_N_bry(days, ice_types, xi_t) ;
		ipondn_N_bry:long_name = "mean melt pond ice thickness - Northern boundary" ;
		ipondn_N_bry:units = "m" ;
	double ipondn_S_bry(days, ice_types, xi_t) ;
		ipondn_S_bry:long_name = "mean melt pond ice thickness - Southern boundary" ;
		ipondn_S_bry:units = "m" ;
	double ipondn_W_bry(days, ice_types, eta_t) ;
		ipondn_W_bry:long_name = "mean melt pond ice thickness - Western boundary" ;
		ipondn_W_bry:units = "m" ;
	double vicen_E_bry(days, ice_types, eta_t) ;
		vicen_E_bry:long_name = "grid cell mean ice thickness - Eastern boundary" ;
		vicen_E_bry:units = "m" ;
	double vicen_N_bry(days, ice_types, xi_t) ;
		vicen_N_bry:long_name = "grid cell mean ice thickness - Northern boundary" ;
		vicen_N_bry:units = "m" ;
	double vicen_S_bry(days, ice_types, xi_t) ;
		vicen_S_bry:long_name = "grid cell mean ice thickness - Southern boundary" ;
		vicen_S_bry:units = "m" ;
	double vicen_W_bry(days, ice_types, eta_t) ;
		vicen_W_bry:long_name = "grid cell mean ice thickness - Western boundary" ;
		vicen_W_bry:units = "m" ;
	double vlvln_E_bry(days, ice_types, eta_t) ;
		vlvln_E_bry:long_name = "volume per unit of area of level ice - Eastern boundary" ;
		vlvln_E_bry:units = "m" ;
	double vlvln_N_bry(days, ice_types, xi_t) ;
		vlvln_N_bry:long_name = "volume per unit of area of level ice - Northern boundary" ;
		vlvln_N_bry:units = "m" ;
	double vlvln_S_bry(days, ice_types, xi_t) ;
		vlvln_S_bry:long_name = "volume per unit of area of level ice - Southern boundary" ;
		vlvln_S_bry:units = "m" ;
	double vlvln_W_bry(days, ice_types, eta_t) ;
		vlvln_W_bry:long_name = "volume per unit of area of level ice - Western boundary" ;
		vlvln_W_bry:units = "m" ;
	double vsnon_E_bry(days, ice_types, eta_t) ;
		vsnon_E_bry:long_name = "grid cell mean snow thickness - Eastern boundary" ;
		vsnon_E_bry:units = "m" ;
	double vsnon_N_bry(days, ice_types, xi_t) ;
		vsnon_N_bry:long_name = "grid cell mean snow thickness - Northern boundary" ;
		vsnon_N_bry:units = "m" ;
	double vsnon_S_bry(days, ice_types, xi_t) ;
		vsnon_S_bry:long_name = "grid cell mean snow thickness - Southern boundary" ;
		vsnon_S_bry:units = "m" ;
	double vsnon_W_bry(days, ice_types, eta_t) ;
		vsnon_W_bry:long_name = "grid cell mean snow thickness - Western boundary" ;
		vsnon_W_bry:units = "m" ;

// global attributes:
		:title = "Boundary condition file for CICE for use in METROMS" ;

@jostbr jostbr self-assigned this Nov 11, 2019
@jostbr jostbr merged commit 6e88426 into master Nov 11, 2019
@nilsmkMET nilsmkMET deleted the cice_obc branch December 2, 2022 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants