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

Modify mesh mask with new mesh_mask_modifier tool #1677

Merged
merged 61 commits into from
Sep 26, 2022
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
c2e59ef
Partial development of mesh_modifier
slevis-lmwg Feb 23, 2022
34e7f00
Partial development of mesh_mask_modifier
slevis-lmwg Mar 4, 2022
01a6337
Merge tag 'ctsm5.1.dev082' into modify_meshes
slevis-lmwg Mar 4, 2022
214ae2c
Partial development of mesh_mask_modifier cont'd
slevis-lmwg Mar 4, 2022
be1b791
mesh_mask_modifier is running it's first test
slevis-lmwg Mar 5, 2022
b0e3fce
Mods for faster turnaround based on @mvertens recomendations
slevis-lmwg Mar 24, 2022
f612b69
Abort if output file exists before starting the calculations
slevis-lmwg Mar 29, 2022
4fae82e
Removing lat/lon inputs from .cfg and making landmask_file required
slevis-lmwg Mar 29, 2022
1a4c383
Replacing references to fsurdat_in/out to file_in/out
slevis-lmwg Mar 29, 2022
37fe56b
Merge tag 'ctsm5.1.dev088' into modify_meshes
slevis-lmwg Mar 29, 2022
b4a429b
Added dummy text to docstring to avoid pylint complaint
slevis-lmwg Mar 29, 2022
bd26ec7
Change one line to read landfrac instead of landmask from file
slevis-lmwg Apr 7, 2022
cc91847
Adding instructions for a specific use-case in the tool's doc-string
slevis-lmwg Apr 12, 2022
7000b25
Adding a line for modify_mesh_mask to /tools/README
slevis-lmwg Apr 20, 2022
6554ccf
Adding README with documentation and instructions
slevis-lmwg Apr 20, 2022
a81e498
Move write_output function to utils.py
slevis-lmwg Apr 21, 2022
d7bc3ba
Merge tag 'ctsm5.1.dev099' into modify_meshes
slevis-lmwg Jun 22, 2022
d522fb0
Update modify_fsurdat & modify_mesh_mask to work w updated landmask.nc
slevis-lmwg Jun 26, 2022
9e8163c
Add error checks that landmask & landmask_diff only equal 0 or 1
slevis-lmwg Jun 28, 2022
98d9372
Allow user to specify lat/lon varnames in the .cfg files for landmask.nc
slevis-lmwg Jun 28, 2022
4f4791b
Add consistency check for landmask <--> landmask_diff
slevis-lmwg Jun 29, 2022
47390f5
Corrections to errors caught by python testing
slevis-lmwg Jun 30, 2022
7bc35ca
Clean-up motivated by pylint recommendations
slevis-lmwg Jun 30, 2022
a120fa5
Draft ChangeLog/ChangeSum; updates to the modify_mesh tool's README
slevis-lmwg Jun 30, 2022
1ff424a
Correction in ChangeLog
slevis-lmwg Jun 30, 2022
632c007
Update documentation about 'conda activate ctsm' and 'ctsm_py'
slevis-lmwg Jul 3, 2022
d0d5018
Update environment instructions in modify_mesh_mask/README
slevis-lmwg Jul 13, 2022
e178df3
Merge tag 'ctsm5.1.dev103' into modify_meshes
slevis-lmwg Jul 14, 2022
e44dc46
Black auto formatting
slevis-lmwg Jul 14, 2022
fa26a22
Pylint recommendations
slevis-lmwg Jul 14, 2022
bab7221
Updated ChangeLog
slevis-lmwg Jul 14, 2022
87887b4
Make modify_mesh_mask & modify_fsurdat work with curvilinear grid
slevis-lmwg Jul 19, 2022
b189d79
Added black autoformat commit to .git-blame-ignore-revs
slevis-lmwg Jul 20, 2022
383fe5a
Fix of error caught by python unit tests
slevis-lmwg Jul 20, 2022
565e7bc
Latest black autoformat
slevis-lmwg Jul 21, 2022
d7ce142
Added 2nd black autoformat commit to .git-blame-ignore-revs
slevis-lmwg Jul 21, 2022
bd781c8
Added two more assert lines
slevis-lmwg Jul 21, 2022
e42ab06
Add flexibility to accept landmask.nc file with lon = -180 to 180
slevis-lmwg Jul 25, 2022
5ff23e6
Correction to fix ability to work with 2d lat/lon variables
slevis-lmwg Jul 25, 2022
88cd401
New error check and reformatted logger.info
slevis-lmwg Jul 25, 2022
b88e1cd
Black and pylint reformatting
slevis-lmwg Jul 26, 2022
bd1ce45
Added black autoformat commit to .git-blame-ignore-revs
slevis-lmwg Jul 26, 2022
1ab4889
Rename landmask_diff to mod_lnd_props (modify lnd properties)
slevis-lmwg Jul 26, 2022
2f38c30
Merge remote-tracking branch 'escomp/master' into modify_meshes
slevis-lmwg Jul 27, 2022
449114f
First (not functioning) draft of test_sys_mesh_modifier.py with TODOs
slevis-lmwg Jul 28, 2022
adc645c
test_sys_mesh_modifier.py now works and the test passes
slevis-lmwg Jul 28, 2022
3569c6b
Obtain lat/lon dim names at run time instead of hardwiring
slevis-lmwg Jul 29, 2022
3f95afd
Updates to ChangeLog
slevis-lmwg Jul 29, 2022
7dacad7
Black/lint updates
slevis-lmwg Jul 29, 2022
d98a1c0
Update .git-blame-ignore-revs
slevis-lmwg Jul 29, 2022
8477d91
Updating README files about module load nco and py_env_create
slevis-lmwg Aug 1, 2022
b69b636
Combining /modify_fsurdat & /modify_mesh_mask into /modify_input_files
slevis-lmwg Aug 1, 2022
492efe3
module load esmf on the fly to avoid harwiring the version
slevis-lmwg Aug 2, 2022
aaf740c
Merge tag 'ctsm5.1.dev108' into modify_meshes
slevis-lmwg Sep 24, 2022
9a2897e
Updated ChangeLog/ChangeSum
slevis-lmwg Sep 25, 2022
78fadfa
Merge remote-tracking branch 'ESCOMP/master' into modify_meshes
ekluzek Sep 26, 2022
70ac7d7
Merge branch 'modify_meshes' of github.com:slevisconsulting/CTSM into…
ekluzek Sep 26, 2022
565f4b6
Update changelog
ekluzek Sep 26, 2022
135690a
Change README notes for new directory to modiufy_input_files
ekluzek Sep 26, 2022
f5106bf
Update date
ekluzek Sep 26, 2022
dd27f4f
Update date
ekluzek Sep 26, 2022
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
4 changes: 4 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@
4cd83cb3ee6d85eb909403487abf5eeaf4d98911
0aa2957c1f8603c63fa30b11295c06cfddff44a5
2cdb380febb274478e84cd90945aee93f29fa2e6
e44dc469439e02e9ee582dab274d890ebdfab104
565e7bcacbb0bba20ff80d680d8ad769676641c6
b88e1cd1b28e3609684c79a2ec0e88f26cfc362b
51c102c5df2e0ef971b5f8eeeb477567899af63a
7dacad70e74e2ec97f6492d4e7a3cb5dd498bcd7
4 changes: 2 additions & 2 deletions cime_config/SystemTests/fsurdatmodifyctsm.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def __init__(self, case):

def _create_config_file(self):
cfg_template_path = os.path.join(self._ctsm_root,
'tools/modify_fsurdat/modify_template.cfg')
'tools/modify_input_files/modify_fsurdat_template.cfg')

with open (self._cfg_file_path,'w') as cfg_out:
with open (cfg_template_path,'r') as cfg_in:
Expand All @@ -64,7 +64,7 @@ def _create_config_file(self):

def _run_modify_fsurdat(self):
tool_path = os.path.join(self._ctsm_root,
'tools/modify_fsurdat/fsurdat_modifier')
'tools/modify_input_files/fsurdat_modifier')
# Need to specify a specific python version that has the required
# dependencies
python_path = _get_python_path()
Expand Down
78 changes: 78 additions & 0 deletions doc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,82 @@
===============================================================
Tag name: ctsm5.1.dev110
Originator(s): slevis (Samuel Levis, 303-665-1310)
Date: Mon Sep 26 11:44:52 MDT 2022
One-line Summary: Introduction of modify_meshes tool for use in I-cases and F-cases

Purpose and description of changes
----------------------------------

Merging the modify_meshes tool to main. This tool is a follow-up to the
modify_fsurdat tool for I- and F-cases where users are adding land to
areas that by default were expected as ocean. In such cases, fsurdat
modifications will take effect only if users also modify the mask_mesh
file which ultimately determines the landmask used by the CTSM.
Details in the tool's README.

Adding test_sys_mesh_modifier.py to python system tests.

Combining /modify_fsurdat and /modify_mesh_mask directories into one
directory: /modify_input_files


Significant changes to scientifically-supported configurations
--------------------------------------------------------------

Does this tag change answers significantly for any of the following physics configurations?
(Details of any changes will be given in the "Answer changes" section below.)

[Put an [X] in the box for any configuration with significant answer changes.]

[ ] clm5_1

[ ] clm5_0

[ ] ctsm5_0-nwp

[ ] clm4_5


Bugs fixed or introduced
------------------------
CTSM issues fixed (include CTSM Issue #):
Fixes #1644 -- Prospective new tool for user to easily modify ocn/lnd mask in their CESM cases

Notes of particular relevance for developers:
---------------------------------------------
Changes to tests or testing:
Adding test_sys_mesh_modifier.py to python system tests. This requires
"module load nco" before running "make stest" or "make all" in the /python
ekluzek marked this conversation as resolved.
Show resolved Hide resolved
directory.

Testing summary:
----------------
[Remove any lines that don't apply.]

[PASS means all tests PASS; OK means tests PASS other than expected fails.]

python testing (if python code has changed; see instructions in python/README.md; document testing done):

cheyenne - PASS
izumi - mostly PASS if approp. environment is loaded, but one test fails
because it requires "module load nco"
clm_pymods on cheyenne - PASS

If the tag used for baseline comparisons was NOT the previous tag, note that here:

Answer changes
--------------

Changes answers relative to baseline: No

Other details
-------------

Pull Requests that document the changes (include PR ids):
https://github.com/ESCOMP/CTSM/pull/1677 -- Modify mesh mask with new mesh_mask_modifier tool

===============================================================
===============================================================
Tag name: ctsm5.1.dev109
Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310)
Date: Mon Sep 26 10:46:33 MDT 2022
Expand Down
1 change: 1 addition & 0 deletions doc/ChangeSum
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Tag Who Date Summary
============================================================================================================================
ctsm5.1.dev110 slevis 09/26/2022 Introduction of modify_meshes tool for use in I-cases and F-cases
ctsm5.1.dev109 slevis 09/26/2022 If not MIMICS, do not output certain MIMICS history fields
ctsm5.1.dev108 afoster 09/08/2022 Connect ozone from atmosphere
ctsm5.1.dev107 afoster 09/07/2022 Update Externals
Expand Down
8 changes: 8 additions & 0 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
To run all tests (unit tests, system tests and pylint), simply run `make
all` from this directory.

When you run `make all`, you need to first execute `module load nco`.

## Python environment

Another way is to use the file conda\_env\_ctsm\_py.txt to setup
Expand Down Expand Up @@ -39,11 +41,17 @@ thing, but support different options:
`make utest` or `make stest`, or they can all be run with `make
test`.

When you run `make test` or `make stest`, you need to first execute
`module load nco`.

2. via `./run_ctsm_py_tests`

You can specify various arguments to this; run `./run_ctsm_py_tests
-h` for details

In any configuration where you run the system tests, you need to
first execute `module load nco`.

## pylint

You can run pylint on everything in the ctsm package with `make lint`.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
"""
Run this code by using the following wrapper script:
tools/modify_fsurdat/fsurdat_modifier
tools/modify_input_files/fsurdat_modifier

The wrapper script includes a full description and instructions.
"""

import os
import logging
import argparse
from configparser import ConfigParser

from ctsm.utils import abort, write_output
from ctsm.config_utils import get_config_value
from ctsm.ctsm_logging import (
setup_logging_pre_config,
add_logging_args,
process_logging_args,
)
from ctsm.modify_fsurdat.modify_fsurdat import ModifyFsurdat
from ctsm.modify_input_files.modify_fsurdat import ModifyFsurdat

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -107,11 +110,30 @@ def fsurdat_modifier(cfg_path):
can_be_unset=True,
)

lat_dimname = get_config_value(
config=config, section=section, item="lat_dimname", file_path=cfg_path, can_be_unset=True
)
lon_dimname = get_config_value(
config=config, section=section, item="lon_dimname", file_path=cfg_path, can_be_unset=True
)

# Create ModifyFsurdat object
modify_fsurdat = ModifyFsurdat.init_from_file(
fsurdat_in, lnd_lon_1, lnd_lon_2, lnd_lat_1, lnd_lat_2, landmask_file
fsurdat_in,
lnd_lon_1,
lnd_lon_2,
lnd_lat_1,
lnd_lat_2,
landmask_file,
lat_dimname,
lon_dimname,
)

# If output file exists, abort before starting work
if os.path.exists(fsurdat_out):
errmsg = "Output file already exists: " + fsurdat_out
abort(errmsg)

# not required: user may set these in the .cfg file
max_pft = int(max(modify_fsurdat.file.lsmpft))
dom_pft = get_config_value(
Expand Down Expand Up @@ -231,4 +253,4 @@ def fsurdat_modifier(cfg_path):
# ----------------------------------------------
# Output the now modified CTSM surface data file
# ----------------------------------------------
modify_fsurdat.write_output(fsurdat_in, fsurdat_out)
write_output(modify_fsurdat.file, fsurdat_in, fsurdat_out, "fsurdat")
90 changes: 90 additions & 0 deletions python/ctsm/modify_input_files/mesh_mask_modifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
Run this code by using the following wrapper script:
tools/modify_input_files/mesh_mask_modifier

The wrapper script includes a full description and instructions.
"""

import os
import logging
import argparse
from configparser import ConfigParser

from ctsm.utils import abort, write_output
from ctsm.config_utils import get_config_value
from ctsm.ctsm_logging import setup_logging_pre_config, add_logging_args, process_logging_args
from ctsm.modify_input_files.modify_mesh_mask import ModifyMeshMask

logger = logging.getLogger(__name__)


def main():
"""
Description
-----------
Calls function that modifies mesh mask
"""

# set up logging allowing user control
setup_logging_pre_config()

# read the command line argument to obtain the path to the .cfg file
parser = argparse.ArgumentParser()
parser.add_argument("cfg_path", help="/path/name.cfg of input file, eg ./modify.cfg")
add_logging_args(parser)
args = parser.parse_args()
process_logging_args(args)
mesh_mask_modifier(args.cfg_path)


def mesh_mask_modifier(cfg_path):
"""Implementation of mesh_mask_modifier command"""
# read the .cfg (config) file
config = ConfigParser()
config.read(cfg_path)
section = config.sections()[0] # name of the first section

# required: user must set these in the .cfg file
mesh_mask_in = get_config_value(
config=config, section=section, item="mesh_mask_in", file_path=cfg_path
)
mesh_mask_out = get_config_value(
config=config, section=section, item="mesh_mask_out", file_path=cfg_path
)
landmask_file = get_config_value(
config=config, section=section, item="landmask_file", file_path=cfg_path
)
lat_dimname = get_config_value(
config=config, section=section, item="lat_dimname", file_path=cfg_path
)
lon_dimname = get_config_value(
config=config, section=section, item="lon_dimname", file_path=cfg_path
)
lat_varname = get_config_value(
config=config, section=section, item="lat_varname", file_path=cfg_path
)
lon_varname = get_config_value(
config=config, section=section, item="lon_varname", file_path=cfg_path
)

# Create ModifyMeshMask object
modify_mesh_mask = ModifyMeshMask.init_from_file(
mesh_mask_in, landmask_file, lat_dimname, lon_dimname, lat_varname, lon_varname
)

# If output file exists, abort before starting work
if os.path.exists(mesh_mask_out):
errmsg = "Output file already exists: " + mesh_mask_out
abort(errmsg)

# ----------------
# modify mesh mask
# ----------------

# Modify mesh mask
modify_mesh_mask.set_mesh_mask("elementMask")

# ----------------------------------------------
# Output the now modified CTSM surface data file
# ----------------------------------------------
write_output(modify_mesh_mask.file, mesh_mask_in, mesh_mask_out, "mesh")
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
"""
Run this code by using the following wrapper script:
/tools/modify_fsurdat/fsurdat_modifier
/tools/modify_input_files/fsurdat_modifier

The wrapper script includes a full description and instructions.
"""

import os
import logging

from math import isclose
import numpy as np
import xarray as xr

from ctsm.git_utils import get_ctsm_git_short_hash
from ctsm.utils import abort, update_metadata
from ctsm.git_utils import get_ctsm_git_short_hash
from ctsm.config_utils import lon_range_0_to_360

logger = logging.getLogger(__name__)
Expand All @@ -24,7 +25,9 @@ class ModifyFsurdat:
-----------
"""

def __init__(self, my_data, lon_1, lon_2, lat_1, lat_2, landmask_file):
def __init__(
self, my_data, lon_1, lon_2, lat_1, lat_2, landmask_file, lat_dimname, lon_dimname
):

self.file = my_data

Expand All @@ -40,17 +43,36 @@ def __init__(self, my_data, lon_1, lon_2, lat_1, lat_2, landmask_file):
if landmask_file is not None:
# overwrite self.not_rectangle with data from
# user-specified .nc file in the .cfg file
self._landmask_file = xr.open_dataset(landmask_file)
self.rectangle = self._landmask_file.landmask
landmask_ds = xr.open_dataset(landmask_file)
self.rectangle = landmask_ds.mod_lnd_props.data
# CF convention has dimension and coordinate variable names the same
if lat_dimname is None: # set to default
lat_dimname = "lsmlat"
if lon_dimname is None: # set to default
lon_dimname = "lsmlon"
lsmlat = landmask_ds.dims[lat_dimname]
lsmlon = landmask_ds.dims[lon_dimname]

for row in range(lsmlat): # rows from landmask file
for col in range(lsmlon): # cols from landmask file
errmsg = (
"landmask_ds.mod_lnd_props not 0 or 1 at "
+ f"row, col, value = {row} {col} {self.rectangle[row, col]}"
)
assert isclose(self.rectangle[row, col], 0, abs_tol=1e-9) or isclose(
self.rectangle[row, col], 1, abs_tol=1e-9
), errmsg

self.not_rectangle = np.logical_not(self.rectangle)

@classmethod
def init_from_file(cls, fsurdat_in, lon_1, lon_2, lat_1, lat_2, landmask_file):
def init_from_file(
cls, fsurdat_in, lon_1, lon_2, lat_1, lat_2, landmask_file, lat_dimname, lon_dimname
):
"""Initialize a ModifyFsurdat object from file fsurdat_in"""
logger.info("Opening fsurdat_in file to be modified: %s", fsurdat_in)
my_file = xr.open_dataset(fsurdat_in)
return cls(my_file, lon_1, lon_2, lat_1, lat_2, landmask_file)
return cls(my_file, lon_1, lon_2, lat_1, lat_2, landmask_file, lat_dimname, lon_dimname)

@staticmethod
def _get_rectangle(lon_1, lon_2, lat_1, lat_2, longxy, latixy):
Expand Down
Loading