Skip to content

Commit 3e4188e

Browse files
committed
r
1 parent dbf0a41 commit 3e4188e

File tree

5 files changed

+450
-173
lines changed

5 files changed

+450
-173
lines changed

README.md

Lines changed: 283 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,295 @@
1-
<h1>Model2roms</h1>
1+
<h1>model2roms</h1>
22

33
[![Build status](https://badge.buildkite.com/8b25e9518aca90534a2a0755dd0623dc91533ba7ca5bd42dde.svg)][image-1]
44
[![codebeat badge](https://codebeat.co/badges/cf0f4bfc-a186-4dfc-9e6a-291b7e985492)][image-2]
55
[![License](https://badge.buildkite.com/8b25e9518aca90534a2a0755dd0623dc91533ba7ca5bd42dde.svg)][image-3]
66
![License][image-4]
77
[![DOI](https://zenodo.org/badge/11505338.svg)](https://zenodo.org/badge/latestdoi/11505338)
88

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
1310

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
1612

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+
![Sea-ice concentration Antarctica](https://github.com/trondkr/model2roms/blob/master/Examples/Figures/temp_Antarctic.png)
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.
18293
19294
<h2>Contact</h2>
20295
<ul>

configM2R.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ def showinfo(self):
4242
self.start_year, self.start_month, self.end_year, self.end_month))
4343
logging.info('[M2R_configM2R]==> The following variables will be interpolated: {}'.format(self.global_varnames))
4444

45-
if self.use_esmf:
46-
logging.info('[M2R_configM2R]=>All horisontal interpolations will be done using ESMF')
45+
logging.info('[M2R_configM2R]=>All horisontal interpolations will be done using ESMF')
4746
logging.info('[M2R_configM2R] => Output files are written in format: {}'.format(self.output_format))
4847
logging.info('[M2R_configM2R] => Output grid file is: {}'.format(self.roms_grid_path))
4948

@@ -125,17 +124,19 @@ def define_atmospheric_forcing_path(self):
125124

126125
def __init__(self):
127126
logging.info('\n--------------------------\n')
128-
print('Started ' + time.ctime(time.time()))
127+
logging.info('Started ' + time.ctime(time.time()))
129128
os.environ['WRAP_STDERR'] = 'true'
130129

131130
# EDIT ===================================================================
132131
# Set show_progress to "False" if you do not want to see the progress
133132
# indicator for horizontal interpolation.
134133
self.show_progress = True
134+
135135
# Set compileAll to True if you want automatic re-compilation of all the
136136
# fortran files necessary to run model2roms. Options are "gfortran" or "ifort". Edit
137137
# compile.py to add other Fortran compilers.
138138
self.compile_all = False
139+
139140
# Extract time-series of data for given longitude/latitude
140141
self.extract_stations = False
141142

@@ -153,25 +154,31 @@ def __init__(self):
153154

154155
# Create the bry, init, and clim files for a given grid and input data
155156
self.create_ocean_forcing = True
157+
156158
# Create atmospheric forcing for the given grid
157159
self.create_atmos_forcing = False # currently in beta stages
160+
158161
# Create a smaller resolution grid based on your original. Decimates every second for
159162
# each time run
160163
self.decimate_gridfile = False
164+
161165
# Write ice values to file (for Arctic regions)
162166
self.write_ice = False
167+
163168
# Write biogeochemistry values to file
164169
self.write_bcg = False
170+
165171
# ROMS sometimes requires input of ice and ssh, but if you dont have these write files containing zeros to file
166172
self.set_2d_vars_to_zero = False
167-
# Use ESMF for the interpolation. This requires that you have ESMF and ESMPy installed (import ESMF)
168-
self.use_esmf = True
173+
169174
# Apply filter to smooth the 2D fields after interpolation (time consuming but enhances results)
170175
self.use_filter = True
176+
171177
# Format to write the ouput to: 'NETCDF4', 'NETCDF4_CLASSIC', 'NETCDF3_64BIT', or 'NETCDF3_CLASSIC'
172178
# Using NETCDF4 automatically turns on compression of files (ZLIB)
173179
self.output_format = 'NETCDF4'
174180
self.use_zlib = True
181+
175182
# Frequency of the input data: usually monthly
176183
self.time_frequency_inputdata = "month" # Possible options: "month", "hour", "5days"
177184

@@ -302,13 +309,13 @@ def create_grd_objects(self):
302309
compile.compileallgfortran()
303310

304311
if self.create_atmos_forcing or self.create_ocean_forcing:
305-
if self.use_esmf:
306-
try:
307-
import ESMF
308-
except ImportError:
309-
raise ImportError("Unable to import ESMF")
310-
logging.info('[M2R_configRunM2R] Starting logfile for ESMF')
311-
ESMF.Manager(debug=True)
312+
313+
try:
314+
import ESMF
315+
except ImportError:
316+
raise ImportError("Unable to import ESMF")
317+
logging.info('[M2R_configRunM2R] Starting logfile for ESMF')
318+
ESMF.Manager(debug=True)
312319

313320
# Create the grid object for the output grid
314321
self.grdROMS = grd.Grd("ROMS", self)

0 commit comments

Comments
 (0)