Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 28 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ libaccessom2 has a single configuration file called `accessom2.nml` which is usu
* `forcing_start_date` the date (and time) when forcing begins.
* `forcing_end_date` the start (and time) at which the forcing ends. The time between the `forcing_start_date` and `forcing_end_date` is called the forcing period. The model will be forced by a continuous repetition of this period.
* `restart_period`: interval of time between successive model restarts. This is provided as a tuple: years, months, seconds. This breaks the entire experiment into a collection of runs or segments.
* `calendar_override` (optional): by default the calendar (`noleap` or `gregorian`) is read from the forcing files and used by both the forcing and experiment clocks. Setting `calendar_override = 'noleap'` runs accessom2 on a `noleap` calendar even when the forcing files are `gregorian`, dropping Feb 29 from the forcing records. The reverse (`calendar_override = 'gregorian'` with `noleap` forcing files) is not currently supported.

These is no configruation option that controls when an experiment ends, it will simply continue until it is stopped.

Expand All @@ -50,7 +51,7 @@ YATM uses two configuration files: `atm.nml`, and `forcing.json`. The latter is

A unique feature of YATM is that it does not read forcing data by iterating over records. That is, the code does not explicitly read and deliver the 1st forcing record followed by the 2nd etc. The reason for this is that when accounting for complications such as different calendar types, fields with different periods, restarts, etc. this approach can quickly become complex and is error prone. Instead YATM iterates over datetime objects. At the current date (and time) YATM finds all matching forcing fields, reads them from disk, delivers them the coupler and then incrementes current date (and time). This simplification has led to much more concise and easy to understand code.

To further simplify things YATM gathers a lot of it's configuration automatically from the forcing dataset metadata. For example the calendar type and timestep information.
To further simplify things YATM gathers a lot of it's configuration automatically from the forcing dataset metadata. For example the default calendar type and timestep information.

## River runoff remapping

Expand All @@ -67,48 +68,59 @@ This repository also includes ice and ocean stubs. These are stand-ins for the t

# Build

How to build libaccessom2, YATM, ice\_stub and ocean\_stub on gadi (NCI):
The easiest way to build libaccessom2, YATM, ice\_stub and ocean\_stub on gadi (NCI) is to use spack:

```{bash}
git clone https://github.com/ACCESS-NRI/libaccessom2.git
cd libaccessom2
./build.sh
module use /g/data/vk83/modules/
module load spack
spack install libaccessom2 dev_path=.
```

# Run tests on Gadi (NCI)

First do build as above. Then to get some computer resources:
To run the tests you will need to install `libaccessom2` and Python packages `pytest`, `numpy`,
`f90nml`, `netcdf4` and `dateutil`. You can set up a spack environment to run the tests as follows:
```
module use /g/data/vk83/modules/
module load spack
spack env create --dir .
spack env activate .
spack add libaccessom2 dev_path=.
spack add py-pytest py-numpy py-f90nml py-netcdf4~mpi py-python-dateutil
spack concretize
spack install
```

```{bash}
qsub -I -P x77 -q normal -lncpus=4 -lmem=16Gb -lwalltime=3:00:00 -lstorage=gdata/ua8+gdata/qv56+gdata/hh5+gdata/ik11
Then get some computer resources and activate your spack environment:

/g/data1b/qv56/
```{bash}
qsub -I -qnormal -lwalltime=3:00:00,ncpus=4,mem=16Gb,storage=gdata/vk83+gdata/ik11+gdata/qv56,wd
module load spack
spack env activate .
ulimit -s unlimited
```

The tests: `JRA55_IAF JRA55_IAF_SINGLE_FIELD JRA55_RYF JRA55_RYF_MINIMAL JRA55_v1p4_IAF` can all be run manually as follows. Replace `JRA55_IAF` with the test to be run.
The tests: `JRA55_IAF JRA55_IAF_SINGLE_FIELD JRA55_RYF JRA55_RYF_MINIMAL` can all be run manually as follows. Replace `JRA55_IAF` with the test to be run.

```{bash}
export LIBACCESSOM2_ROOT=$(pwd)
module load openmpi
cd tests/
./copy_test_data.sh
cd JRA55_IAF
rm -rf log ; mkdir log ; rm -f accessom2_restart.nml ; cp ../test_data/i2o.nc ./ ; cp ../test_data/o2i.nc ./
export UCX_LOG_LEVEL=error; mpirun -np 1 $LIBACCESSOM2_ROOT/build/bin/yatm.exe : -np 1 $LIBACCESSOM2_ROOT/build/bin/ice_stub.exe : -np 1 $LIBACCESSOM2_ROOT/build/bin/ocean_stub.exe
export UCX_LOG_LEVEL=error; mpirun -np 1 yatm.exe : -np 1 ice_stub.exe : -np 1 ocean_stub.exe
```

If Python3 and pytest are installed then all of the above and some additional tests can be run with:
With the above Python packages installed, all of the above and some additional tests can be run with:

```{bash}
module load openmpi
python -m pytest tests/
```

Any individual pytest test can be run using pytest as follows:

```{bash}
module load openmpi
python -m pytest test_stubs.py::TestStubs::test_field_scaling
python -m pytest tests/test_stubs.py::TestStubs::test_forcing_perturbations
```

The above is the only way to run the `FORCING_SCALING` test case because it relies on the Python test code to create one of the inputs.
Expand Down
54 changes: 48 additions & 6 deletions libcouple/src/accessom2.F90
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ module accessom2_mod
use datetime_module, only : date2num, num2date
use error_handler, only : assert
use coupler_mod, only : coupler_type => coupler
use logger_mod, only : logger_type => logger, LOG_ERROR
use logger_mod, only : logger_type => logger, LOG_ERROR, LOG_INFO
use libaccessom2_version_mod, only : LIBACCESSOM2_VERSION

implicit none
Expand Down Expand Up @@ -43,6 +43,10 @@ module accessom2_mod

logical :: allow_forcing_and_exp_date_mismatch

! Optional user override of the calendar otherwise derived from the
! forcing files, see accessom2_set_calendar.
character(len=9) :: calendar_override

character(len=9) :: calendar_str
integer :: calendar

Expand Down Expand Up @@ -113,13 +117,14 @@ module accessom2_mod
character(len=19) :: exp_cur_date, forcing_cur_date
integer, dimension(3) :: restart_period
logical :: allow_forcing_and_exp_date_mismatch
character(len=9) :: calendar_override
character(len=8) :: log_level
logical :: enable_simple_timers
integer :: ice_ocean_timestep

namelist /accessom2_nml/ log_level, ice_ocean_timestep, enable_simple_timers
namelist /date_manager_nml/ forcing_start_date, forcing_end_date, &
restart_period, allow_forcing_and_exp_date_mismatch
restart_period, allow_forcing_and_exp_date_mismatch, calendar_override
namelist /do_not_edit_nml/ forcing_cur_date, exp_cur_date

contains
Expand Down Expand Up @@ -155,6 +160,7 @@ subroutine accessom2_init(self, model_name, config_dir)
ice_ocean_timestep = 300
enable_simple_timers = .false.
allow_forcing_and_exp_date_mismatch = .false.
calendar_override = ''

! Read namelist which includes information about the forcing start and end date
path = trim(config_dir)//'/'//trim(config_file)
Expand Down Expand Up @@ -182,6 +188,14 @@ subroutine accessom2_init(self, model_name, config_dir)
self%restart_period = restart_period
self%allow_forcing_and_exp_date_mismatch = allow_forcing_and_exp_date_mismatch

if (len_trim(calendar_override) > 0) then
call assert(trim(calendar_override) == 'noleap' .or. &
trim(calendar_override) == 'gregorian', &
Comment thread
dougiesquire marked this conversation as resolved.
'accessom2_init: calendar_override must be one of '// &
"'noleap' or 'gregorian', got: "//trim(calendar_override))
endif
self%calendar_override = calendar_override

! Read in exp_cur_date and focing_cur_date from restart file.
! Try to read from config dir first.
path = trim(config_dir)//'/'//trim(restart_file)
Expand Down Expand Up @@ -220,16 +234,44 @@ subroutine accessom2_init(self, model_name, config_dir)

endsubroutine accessom2_init

!> Set the calendar. This is derived by the caller from the forcing files unless
! calendar_override was supplied in date_manager_nml. The calendar_override param
! provides a way to set the accessom2 calendar differently from the calendar in
! the forcing files. Only overriding with calendar_override="noleap" is currently
! supported, to allow running accessom2 with a noleap calendar but using forcing
! with a gregorian calendar.
subroutine accessom2_set_calendar(self, calendar)
class(accessom2), intent(inout) :: self
character(len=*), intent(in) :: calendar

self%calendar_str = calendar
if (index(trim(calendar), 'noleap') /= 0) then
character(len=9) :: effective_calendar

effective_calendar = trim(calendar)

if (len_trim(self%calendar_override) > 0 .and. &
trim(self%calendar_override) /= trim(effective_calendar)) then

call assert(trim(self%calendar_override) == 'noleap' .and. &
trim(effective_calendar) == 'gregorian', &
'accessom2_set_calendar: calendar_override='//trim(self%calendar_override)// &
' was requested but the forcing files use calendar='// &
trim(effective_calendar)//'. Only overriding gregorian forcing to run'// &
' on noleap is currently supported (this drops Feb 29 records).')

call self%logger%write(LOG_INFO, &
'accessom2_set_calendar: forcing files use calendar='//trim(effective_calendar)// &
' but calendar_override='//trim(self%calendar_override)//' was set. Feb 29 records'// &
' will be dropped from the forcing data.')

effective_calendar = self%calendar_override
endif

self%calendar_str = effective_calendar
if (index(trim(effective_calendar), 'noleap') /= 0) then
self%calendar = CALENDAR_NOLEAP
else
call assert(index(trim(calendar), 'gregorian') /= 0, &
'accessom2_set_calendar: Unsupported calendar type: '//trim(calendar))
call assert(index(trim(effective_calendar), 'gregorian') /= 0, &
'accessom2_set_calendar: Unsupported calendar type: '//trim(effective_calendar))
self%calendar = CALENDAR_GREGORIAN
endif

Expand Down
Loading
Loading