A bio_toy sensitivity study¶
This example provides a simple demonstration of the ROMS Communication Toolbox, applied to the ROMS bio_toy
test case.
The original test case can be found in ROMS Test Cases repository. It provides a simple one-dimensional (vertical) ocean environment that is ideal for testing biological models. It also comes with input files to compile and run all the standard biological models that ship with the myroms.org version of ROMS. This example will focus on the NPZD variants.
This example focuses on demonstrating the toolbox, and as such never actively calls ROMS. Therefore, this example should run cleanly without the need to fully set up and configure the bio_toy
configurations.
# Module imports
import os
from datetime import datetime, timedelta
import romscom.romscom as rc
Import default parameters¶
We start by importing the model parameters, including physical ocean model parameters as well as additional biological parameters for the three models we will focus on: NPZD_FRANKS, NPZD_IRON, and NPZD_POWELL.
# Ocean parameters
ocean = rc.readparamfile("roms_bio_toy_npzd.yaml", tconvert=True)
# Bio parameters
bioname = ["Franks", "iron", "Powell"]
bio = [rc.readparamfile(f"npzd_{x}.yaml") for x in bioname]
Note that we set the tconvert
flag on the ocean parameters to True
, which tells the reader to convert all time-related fields to datetimes and timedeltas. For example, the NTIMES
parameter is set to 1600 the original file. The convertion combines this with the DT
parameter to figure out the duration of the desired simulation.
ocean['DT']
datetime.timedelta(seconds=540)
ocean['NTIMES']
datetime.timedelta(days=10)
If we wanted to change the time step DT
, we could do so without needing to recalculate any of the parameters that rely on it; those will be automatically updated when we convert the format later.
In this example, we're going to use the runtodate
function, which means we don't need to manually set either of these variables.
The experiment¶
We can now set up our toy experiment. Here, we'll run a simple sensitivity study to run the three models with varying initial nitrate concentrations (i.e, BioIni(iNO3_)
, a parameter shared by all three models.)
These simulations will rely on the data files found in the roms_test/biotoy/Data
folder from the ROMS Test Cases repository. Update the following path to reflect your own copy of this data.
# Local path to data directory
biotoy_dir = "/Users/kelly.kearney/Documents/Repos/ESMs/roms_test/bio_toy"
# Modify relevant input file names to reflect full path
ocean['GRDNAME'] = os.path.join(biotoy_dir, "Data", "bio_toy_grd.nc")
ocean['ININAME'] = os.path.join(biotoy_dir, "Data", "bio_toy_ini_npzd.nc")
ocean['FRCNAME'] = os.path.join(biotoy_dir, "Data", "bio_toy_frc.nc")
From here, we can set up the main experiments. The code below loops over each of our biological model and initial nitrate concentration combinations, running (or previewing) a one-year simulation for each.
# Initial nitrate values
no3 = [1, 10, 20]
# One set of output folders for all runs
# You could alternatively create a separate subfolder for each, but
# I'm keeping it simple for this example
simfol = rc.simfolders(".", create=True)
# Loop over sensitivity simulations...
for ii in range(0,len(bioname)):
for ino3 in range(0,len(no3)):
sname = f"npzd_{bioname[ii]}{ino3+1}"
# Create the new BPARNAM file with the correct initial nitrate, and
# place it in the new input subfolder
ocean['BPARNAM'] = os.path.join(simfol['in'], f"{sname}_bpar.in")
bio[ii]['BioIni']['iNO3_'] = no3[ii]
rc.dict2standardin(bio[ii], file=ocean['BPARNAM'])
# Run simulations
rc.runtodate(ocean, ".", sname, datetime(2002,1,1), dryrunflag=True)
Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_Franks1_01_ocean.in Standard output: ./Log/npzd_Franks1_01_log.txt Standard error: ./Log/npzd_Franks1_01_err.txt Dry run Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_Franks2_01_ocean.in Standard output: ./Log/npzd_Franks2_01_log.txt Standard error: ./Log/npzd_Franks2_01_err.txt Dry run Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_Franks3_01_ocean.in Standard output: ./Log/npzd_Franks3_01_log.txt Standard error: ./Log/npzd_Franks3_01_err.txt Dry run Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_iron1_01_ocean.in Standard output: ./Log/npzd_iron1_01_log.txt Standard error: ./Log/npzd_iron1_01_err.txt Dry run Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_iron2_01_ocean.in Standard output: ./Log/npzd_iron2_01_log.txt Standard error: ./Log/npzd_iron2_01_err.txt Dry run Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_iron3_01_ocean.in Standard output: ./Log/npzd_iron3_01_log.txt Standard error: ./Log/npzd_iron3_01_err.txt Dry run Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_Powell1_01_ocean.in Standard output: ./Log/npzd_Powell1_01_log.txt Standard error: ./Log/npzd_Powell1_01_err.txt Dry run Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_Powell2_01_ocean.in Standard output: ./Log/npzd_Powell2_01_log.txt Standard error: ./Log/npzd_Powell2_01_err.txt Dry run Running ROMS simulation Counter block: 1 Start date: 2001-01-01 12:00:00 End date: 2002-01-01 00:00:00 ROMS command: mpirun romsM Standard input: ./In/npzd_Powell3_01_ocean.in Standard output: ./Log/npzd_Powell3_01_log.txt Standard error: ./Log/npzd_Powell3_01_err.txt Dry run
Because we set the dryrun option to True, the output status at the bottom of each run block simply reads "Dry run." If this flag were false, the script would instead execute the ROMS command and then state whether the simulation completed successfully, encountered a blow-up error that couldn't be resolved with time step reduction, or terminated with another error.
Note: The warnings toward the end are generated by romscom's simple file check. In this case, these all correspond to files that are unused by the bio_toy-configured ROMS executable. The romscom functions will suppress the warning if a filename starts with the word "placeholder"; I find this a useful way to track which files are knowingly ommitted in an application. Another common tactic is to point those file variables to /dev/null (the null device file), as is done in this particular example for many of the unnecessary input files. The few remaining "Cannot find" messages point to files assoicated with options that could in theory be turned on in some bio_toy use cases, and therefore were not explicity set to /dev/null in the original input files. I've preserved that in my .yaml versions here. The warnings can be ignored, but serve as a useful reminder to double-check if indeed you intend to make use of those options in your compilation.