|
1 | | -<h1>Model2roms</h1> |
| 1 | +<h1>model2roms</h1> |
2 | 2 |
|
3 | 3 | [][image-1] |
4 | 4 | [][image-2] |
5 | 5 | [][image-3] |
6 | 6 | ![License][image-4] |
7 | 7 | [](https://zenodo.org/badge/latestdoi/11505338) |
8 | 8 |
|
9 | | -[image-1]: https://buildkite.com/rask-dev-llc/model2roms |
10 | | -[image-2]: https://codebeat.co/projects/github-com-trondkr-model2roms-master |
11 | | -[image-3]: https://badge.buildkite.com/8b25e9518aca90534a2a0755dd0623dc91533ba7ca5bd42dde.svg |
12 | | -[image-4]: https://img.shields.io/github/last-commit/trondkr/model2roms.svg |
| 9 | +[image-1]: https://buildkite.com/rask-dev-llc/model2roms |
13 | 10 |
|
14 | | -Model2roms is a Python toolbox for creating the necessary climatology, boundary, and initial forcing files |
15 | | -required to run the ROMS (<a href="http://myroms.org/" target="_blank">Regional Ocean Modeling System</a>) model. The latest version of model2roms can convert several popular model hindcasts and projections including the NORESM (Norways Earth System Model), SODA global re-analysis, HYCOM, World Ocean Atlas (WOA), and GLORYS (Mercator Ocean) to a use as forcing files for a given ROMS grid structure. |
| 11 | +[image-2]: https://codebeat.co/projects/github-com-trondkr-model2roms-master |
16 | 12 |
|
17 | | -More detailed information on how to use and install is available in the [Wiki](https://github.com/trondkr/model2roms/wiki/Introduction-to-model2roms) |
| 13 | +[image-3]: https://badge.buildkite.com/8b25e9518aca90534a2a0755dd0623dc91533ba7ca5bd42dde.svg |
| 14 | + |
| 15 | +[image-4]: https://img.shields.io/github/last-commit/trondkr/model2roms.svg |
| 16 | + |
| 17 | +Model2roms is a Python toolbox for creating the necessary climatology, boundary, and initial forcing files required to |
| 18 | +run the ROMS (<a href="http://myroms.org/" target="_blank">Regional Ocean Modeling System</a>) model. The latest version |
| 19 | +of model2roms can convert several popular model hindcasts and projections including the NORESM (Norways Earth System |
| 20 | +Model), SODA global re-analysis, HYCOM, World Ocean Atlas (WOA), and GLORYS (Mercator Ocean) to a use as forcing files |
| 21 | +for a given ROMS grid structure. |
| 22 | + |
| 23 | +<h3>Introduction</h3> |
| 24 | + |
| 25 | +Model2roms is a Python toolbox for creating the necessary climatology, boundary, and initial forcing files required to |
| 26 | +run the ROMS (<a href="http://myroms.org/" target="_blank">Regional Ocean Modeling System</a>) model. The latest version |
| 27 | +of model2roms can convert several popular model hindcasts and projections including the NORESM |
| 28 | +(Norways Earth System Model) |
| 29 | +, **[SODA](https://climatedataguide.ucar.edu/climate-data/soda-simple-ocean-data-assimilation)** |
| 30 | +global re-analysis, and |
| 31 | +**[GLORYS](https://resources.marine.copernicus.eu/?option=com_csw&view=details&product_id=GLOBAL_REANALYSIS_PHY_001_030)** |
| 32 | +(Mercator Ocean) to be used as forcing files for a given ROMS grid structure. |
| 33 | + |
| 34 | +Model2roms uses the Earth System Modeling Framework (ESMF) as the default interpolation method. This allows the input |
| 35 | +data to be on any kind of grid structure (e.g. irregular) provided that geographical information such as the longitude |
| 36 | +and latitude of grid cells is available. The implementation uses the Python interface to ESMF which can be found |
| 37 | +here: <a href="https://www.earthsystemcog.org/projects/esmpy/" target="_blank">www.earthsystemcog.org/projects/esmpy/</a> |
| 38 | +. Using ESMF significantly increases the speed of the interpolation. As an example, interpolating one variable |
| 39 | +(e.g. temperature distribution) from a global irregular grid to a local non-rectangular grid of size 1250x789, at 70 |
| 40 | +different depth levels, takes 3 seconds on a Mac Laptop Pro. For most people, installing using Anaconda would be the |
| 41 | +best option to install the required packages to run <b>model2roms</b>. The minimum installation of required packages: |
| 42 | + |
| 43 | +```bash |
| 44 | +conda create -n model2roms` |
| 45 | +conda config --add channels conda-forge |
| 46 | +conda activate model2roms |
| 47 | +conda install esmf xarray netcdf4 progressbar2 |
| 48 | +``` |
| 49 | + |
| 50 | + |
| 51 | + |
| 52 | +Model2roms has been developed over several years, usually improved every time a new model configuration of ROMS has been |
| 53 | +required for my work. But the user groups of model2roms has also increased over these years and several people have |
| 54 | +pointed out bugs and ways to improve this package. The toolbox consists of collection of Python and Fortran modules that |
| 55 | +can be used to create climatology (CLIM), initial (INIT), and boundary (BRY) files necessary to run |
| 56 | +the <a href="www.myroms.org">ROMS</a> model. |
| 57 | + |
| 58 | +Currently, model2roms takes rectangular gridded forcing files at Z-levels as input. These data are first interpolated to |
| 59 | +the ROMS grid at Z-levels. Next the Z-levels are interpolated vertically to the sigma layers |
| 60 | +(<a href="https://www.myroms.org/wiki/index.php/Vertical_S-coordinate">S-coordinates</a>). For U and V velocities, the |
| 61 | +interpolation is done at RHO points, and then interpolated to U and V points ((eta_u,xi_u), and (eta_v, xi_v)). All |
| 62 | +interpolated values are written to netCDF4 files using compression (zlib) to minimize file size. The result of running |
| 63 | +model2roms is one file for each CLIM, INIT, and BRY files. UBAR and VBAR (barotropic flow) are calculated from U and V |
| 64 | +velocities. Time is stored as julian day from 01/01/1948 (see model2roms.py) |
| 65 | + |
| 66 | +<h4>Compile the Fortran modules</h4> |
| 67 | +To get started, compile the Fortran functions into modules callable by Python. First edit the file compile.py and select |
| 68 | +your Fortran compiler (currently gfortran and Intel Fortran compiler supported): |
| 69 | + |
| 70 | +```python |
| 71 | +python |
| 72 | +compile.py |
| 73 | +``` |
| 74 | + |
| 75 | +Make sure that this successfully creates modules (.so files) that Python can import. Some users have reported that they |
| 76 | +have to run each compile command individually to compile (this may depend on your machine and OS). The use of Fortran |
| 77 | +modules as part of the calculations significantly speeds up the calculations. |
| 78 | + |
| 79 | +<h4>Running model2roms</h4> |
| 80 | +Before you run model2roms you have to edit the configuration file `configM2R.py` to correctly point to the path of your |
| 81 | +gridfile, the type of forcing you want and the variables to use. |
| 82 | + |
| 83 | +Once everything is correctly setup you can run model2roms with the command: |
| 84 | + |
| 85 | +```python |
| 86 | +python |
| 87 | +runM2R.py |
| 88 | +``` |
| 89 | + |
| 90 | +<h4>Options for interpolation</h4> |
| 91 | +Model2roms makes use of the ESMF python package to handle all the horizontal interpolations. This has significantly sped |
| 92 | +up the time used on interpolation and also made interpolation more robust across the poles. |
| 93 | +In addition, ESMF can handle any input type grid and therefore making it very easy to convert any type of model into |
| 94 | +forcing files for ROMS. However, often the target grid has higher resolution than the source grid which opens up areas |
| 95 | +(e.g. along the coastlines) where you have no data. Model2roms contains an option `use_filter` that will extrapolate |
| 96 | +data to fill these areas with no data using a Laplace operator. This is quite useful, but also time-consuming and should |
| 97 | +be turned off unless you need it: |
| 98 | + |
| 99 | +Without filter | With filter |
| 100 | +:-------------------------:|:-------------------------: |
| 101 | +<img src="http://www.trondkristiansen.com/wp-content/gallery/romstools/temperature_depth_ESMF_0_withoutfilter_time_75190.0.png" width=100%> | <img src="http://www.trondkristiansen.com/wp-content/gallery/romstools/temperature_depth_ESMF_0_withfilter_time_75190.0.png" width=100%> |
| 102 | + |
| 103 | +<h3>Optional settings</h3> |
| 104 | +Prior to run model2roms you have to specify a number of settings so that the program can identify where input and grid |
| 105 | +files can be found. In addition, you can specify what sort of run you are doing by turning options on and off. All of |
| 106 | +the user settings are done in `configM2R.py`, a few definitions for variable names are found in `model2roms.py`, and |
| 107 | +finally a few settings for the grid specifications are found in `grd.py`. Eventually, all of the settings will be moved |
| 108 | +to one file. Still, the main settings are the following: |
| 109 | + |
| 110 | +```Python |
| 111 | + def __init__(self): |
| 112 | + logging.info('\n--------------------------\n') |
| 113 | + logging.info('Started ' + time.ctime(time.time())) |
| 114 | + os.environ['WRAP_STDERR'] = 'true' |
| 115 | +
|
| 116 | + # EDIT =================================================================== |
| 117 | + # Set show_progress to "False" if you do not want to see the progress |
| 118 | + # indicator for horizontal interpolation. |
| 119 | + self.show_progress = True |
| 120 | +
|
| 121 | + # Set compileAll to True if you want automatic re-compilation of all the |
| 122 | + # fortran files necessary to run model2roms. Options are "gfortran" or "ifort". Edit |
| 123 | + # compile.py to add other Fortran compilers. |
| 124 | + self.compile_all = False |
| 125 | +
|
| 126 | + # Extract time-series of data for given longitude/latitude |
| 127 | + self.extract_stations = False |
| 128 | +
|
| 129 | + # Define a set of longitude/latitude positions with names to extract into |
| 130 | + # station files (using extractStations) |
| 131 | + if self.extract_stations: |
| 132 | + # stationNames = ['NorthSea', 'Iceland', 'EastandWestGreenland', 'Lofoten', 'Georges Bank'] |
| 133 | + # lonlist = [2.4301, -22.6001, -47.0801, 13.3801, -67.2001] |
| 134 | + # latlist = [54.5601, 63.7010, 60.4201, 67.5001, 41.6423] |
| 135 | +
|
| 136 | + self.station_names = ["Ytre Utsira", "Indre Utsira", "Lista"] |
| 137 | + self.latlist = [59.316667, 59.316667, 58.016667] |
| 138 | + self.lonlist = [4.800000, 4.983333, 6.533333] |
| 139 | + self.numberofpoints = 4 # Number of points around lat/lon to extract and average as output |
| 140 | +
|
| 141 | + # Create the bry, init, and clim files for a given grid and input data |
| 142 | + self.create_ocean_forcing = True |
| 143 | +
|
| 144 | + # Create atmospheric forcing for the given grid |
| 145 | + self.create_atmos_forcing = False # currently in beta stages |
| 146 | +
|
| 147 | + # Create a smaller resolution grid based on your original. Decimates every second for |
| 148 | + # each time run |
| 149 | + self.decimate_gridfile = False |
| 150 | +
|
| 151 | + # Write ice values to file (for Arctic regions) |
| 152 | + self.write_ice = False |
| 153 | +
|
| 154 | + # Write biogeochemistry values to file |
| 155 | + self.write_bcg = False |
| 156 | +
|
| 157 | + # ROMS sometimes requires input of ice and ssh, but if you dont have these write files containing zeros to file |
| 158 | + self.set_2d_vars_to_zero = False |
| 159 | +
|
| 160 | + # Apply filter to smooth the 2D fields after interpolation (time consuming but enhances results) |
| 161 | + self.use_filter = True |
| 162 | +
|
| 163 | + # Format to write the ouput to: 'NETCDF4', 'NETCDF4_CLASSIC', 'NETCDF3_64BIT', or 'NETCDF3_CLASSIC' |
| 164 | + # Using NETCDF4 automatically turns on compression of files (ZLIB) |
| 165 | + self.output_format = 'NETCDF4' |
| 166 | + self.use_zlib = True |
| 167 | +
|
| 168 | + # Frequency of the input data: usually monthly |
| 169 | + self.time_frequency_inputdata = "month" # Possible options: "month", "hour", "5days" |
| 170 | +
|
| 171 | + # Path to where results files should be stored |
| 172 | + self.outdir = "../oceanography/NAUTILOS/" |
| 173 | + if not os.path.exists(self.outdir): |
| 174 | + os.makedirs(self.outdir, exist_ok=True) |
| 175 | +
|
| 176 | + # IN GRIDTYPES ------------------------------------------------------------------------------ |
| 177 | + # Define what grid type you want to interpolate from (input MODEL data) |
| 178 | + # Currently supported options: |
| 179 | + # 1. NORESM, 2. GLORYS, 3. SODA3, 4. SODA3_5DAY |
| 180 | + self.ocean_indata_type = 'GLORYS' |
| 181 | + self.atmos_indata_type = 'ERA5' |
| 182 | +
|
| 183 | + # Define contact info for final NetCDF files |
| 184 | + self.author_name = "Trond Kristiansen" |
| 185 | + self.author_email = "trond.kristiansen (at) niva.no" |
| 186 | +
|
| 187 | + # Define what grid type you wnat to interpolate from: Can be Z for SIGMA for ROMS |
| 188 | + # vertical coordinate system or ZLEVEL. also define the name of the dimensions in the input files. |
| 189 | + # Options: |
| 190 | + # 1. SIGMA (not properly implemented yet), 2. ZLEVEL |
| 191 | + self.ingrid_type = "ZLEVEL" # "ZLEVEL" |
| 192 | +
|
| 193 | + # Define the names of the geographical variables in the input files. These may |
| 194 | + # differ depending how the variable is located in a grid (e.g. Arakawa C grid - ROMS). In |
| 195 | + # SODA 3.3.1 the u and v location is defined by xu_ocean, yu_ocean while temperature is |
| 196 | + # located in xt_ocean, yt_ocean. |
| 197 | + self.grd_type = 'regular' |
| 198 | + self.lon_name = "longitude" |
| 199 | + self.lat_name = "latitude" |
| 200 | + self.depth_name = "depth" |
| 201 | + self.lon_name_u = "longitude" |
| 202 | + self.lat_name_u = "latitude" |
| 203 | + self.lon_name_v = "longitude" |
| 204 | + self.lat_name_v = "latitude" |
| 205 | +
|
| 206 | + if self.ocean_indata_type == 'SODA3_5DAY': |
| 207 | + self.lon_name = "xt_ocean" |
| 208 | + self.lat_name = "yt_ocean" |
| 209 | + self.depth_name = "st_ocean" |
| 210 | + self.lon_name_u = "xu_ocean" |
| 211 | + self.lat_name_u = "yu_ocean" |
| 212 | + self.lon_name_v = "xu_ocean" |
| 213 | + self.lat_name_v = "yu_ocean" |
| 214 | + self.time_object = [] |
| 215 | +
|
| 216 | + self.time_name = "time" |
| 217 | + self.realm = "ocean" |
| 218 | + self.fillvaluein = -32767 |
| 219 | +
|
| 220 | + # OUT GRIDTYPES ------------------------------------------------------------------------------ |
| 221 | + # Define what grid type you want to interpolate to |
| 222 | + # Options: This is just the name of your grid used to identify your selection later |
| 223 | + self.outgrid_name = 'ROHO160' # "ROHO800", "A20" |
| 224 | + self.outgrid_type = "ROMS" |
| 225 | +
|
| 226 | + # Subset input data. If you have global data you may want to seubset these to speed up reading. Make |
| 227 | + # sure that your input data are cartesian (0-360 or -180:180, -90:90) |
| 228 | + self.subset_indata = False |
| 229 | + if self.subset_indata: |
| 230 | + self.subset = self.define_subset_for_indata() |
| 231 | +
|
| 232 | + # Define nmber of output depth levels |
| 233 | + self.nlevels = 40 |
| 234 | + # Define the grid stretching properties (leave default if uncertain what to pick) |
| 235 | + self.vstretching = 4 |
| 236 | + self.vtransform = 2 |
| 237 | + self.theta_s = 7.0 |
| 238 | + self.theta_b = 0.1 |
| 239 | + self.tcline = 250.0 |
| 240 | + self.hc = 250 |
| 241 | +
|
| 242 | + # PATH TO FORCING DATA -------------------------------------------------------------------- |
| 243 | + # Define the path to the input data |
| 244 | + self.ocean_forcing_path = self.define_ocean_forcing_data_path() |
| 245 | + self.atmospheric_forcing_path = self.define_atmospheric_forcing_path() |
| 246 | +
|
| 247 | + # PATH TO GRID ----------------------------------------------------------------------------- |
| 248 | + # Define the path to the grid file |
| 249 | + self.roms_grid_path = self.define_roms_grid_path() |
| 250 | +
|
| 251 | + # Climatology is only monthly and model2roms needs to know this |
| 252 | + self.isclimatology = False |
| 253 | +
|
| 254 | + # DATE AND TIME DETAILS --------------------------------------------------------- |
| 255 | + # Define the period to create forcing for |
| 256 | + self.start_year = 2017 |
| 257 | + self.end_year = 2019 |
| 258 | + self.start_month = 1 |
| 259 | + self.end_month = 11 |
| 260 | + self.start_day = 15 |
| 261 | + self.end_day = 31 |
| 262 | +``` |
| 263 | +
|
| 264 | +<p style="clear: both;"> |
| 265 | +
|
| 266 | +<h2>Contact</h2> |
| 267 | +<ul> |
| 268 | +<li>me @ trondkristiansen.com</li> |
| 269 | +<li>http://github.com/trondkr</li> |
| 270 | +<li>www.trondkristiansen.com</li> |
| 271 | +</ul> |
| 272 | +Please send a comment on suggestions, questions, or modifications and improvements you would like to |
| 273 | +make to me @ trondkristiansen.com. I would very much like to see this project go much further so that it can be |
| 274 | +useful for a variety of purposes. |
| 275 | +
|
| 276 | +<h2>License</h2> |
| 277 | +The MIT License (MIT) |
| 278 | +
|
| 279 | +Copyright (c) <year> <copyright holders> |
| 280 | +
|
| 281 | +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated |
| 282 | +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the |
| 283 | +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit |
| 284 | +persons to whom the Software is furnished to do so, subject to the following conditions: |
| 285 | +
|
| 286 | +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the |
| 287 | +Software. |
| 288 | +
|
| 289 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| 290 | +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| 291 | +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| 292 | +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
18 | 293 |
|
19 | 294 | <h2>Contact</h2> |
20 | 295 | <ul> |
|
0 commit comments