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

Add a tool to create transect cell and edge fields with edge sign and distance #7

Open
wants to merge 102 commits into
base: master
Choose a base branch
from

Conversation

xylar
Copy link
Collaborator

@xylar xylar commented Jun 5, 2024

See the new README for how to use it.

@xylar xylar requested a review from alicebarthel June 5, 2024 13:28
@xylar xylar self-assigned this Jun 5, 2024
@xylar
Copy link
Collaborator Author

xylar commented Jun 5, 2024

@alicebarthel, I think this tool will be helpful for the transport plots you're working on.

It needs to be used in conjunction with MPAS-Dev/geometric_features#202 so we'll need to discuss special instructions for how to install that verson of geometric_features before it gets released. Here's the gist.

Create a new environment with the dependences:

conda create -y -n transects python=3.12 geometric_features matplotlib mpas_tools netcdf4 numpy scipy shapely xarray
conda activate transects

Then, go to the location where you've checked out MPAS-Dev/geometric_features#202

python -m pip install -e .
export GEOMETRIC_DATA_DIR=$PWD/geometric_data

(You'll need to set GEOMETRIC_DATA_DIR each time you want to use this conda environment or it won't find the new transect).

To run this code, go into the subdirectory:

cd ocean/transects/python

Then, you will need to find the initial condition you want, e.g.:

ln -s /lcrc/group/e3sm/public_html/inputdata/ocn/mpas-o/SOwISC12to60E2r4/ocean.SOwISC12to60E2r4.230220.nc

and then run:

./create_transect_masks.py -m SOwISC12to60E2r4.230220.nc -f "Antarctic isobath at -1000.0 m" -o SOwISC12to60E2r4_Antarctic_isobath_at_-1000.0_m.nc --process_count 4

You could safely run with more processes if you run on a compute node. The resulting fields on cells and edges should be useful masks, distances and edge sign (on edges, of course).

As an example, here's the distance on edges:
distance_edges

@milenaveneziani
Copy link
Collaborator

@xylar: this immediately caught my attention, since I've been doing lots of transects and regional open boundary calculations lately.
@alicebarthel: do you know how this is different from the workflow I usually use (get mask through MpasMaskCreator and find edges of transects to plot/compute quantities)?
Thanks!

@xylar
Copy link
Collaborator Author

xylar commented Jun 5, 2024

@milenaveneziani, the main added value here is that we needed distance along the transect at each edge where the edge sign is non-zero. I don't think we have a way to compute that anywhere else so that's the added value here.

@xylar
Copy link
Collaborator Author

xylar commented Jun 5, 2024

get mask through MpasMaskCreator and find edges of transects to plot/compute quantities

The edge mask and edge sign is found with the python version of the mask creator but it's otherwise pretty similar.

The distance along the transect is computed first at every place that a transect segment intersects with the edges of an MPAS cell (something we already had for MPAS-Analysis), then those distances are averaged back to cells or edges based on all the segments that cross the cell or the diamond shape associated with an edge.

Comment on lines +72 to +107
def add_distance_field(ds, logger):
"""
Add fields on edges and cells that define the (mean) distance along the
transect for each cell or edge in the transect
"""

dist_cell = np.zeros(ds.sizes['nCells'])
count_cell = np.zeros(ds.sizes['nCells'], dtype=int)
dist_edge = np.zeros(ds.sizes['nEdges'])
count_edge = np.zeros(ds.sizes['nEdges'], dtype=int)

logger.info('Adding transect distance fields on cells and edges...')

for segment in range(ds.sizes['nSegments']):
icell = ds.horizCellIndices.isel(nSegments=segment).values
iedge = ds.horizEdgeIndices.isel(nSegments=segment).values
# the distance for the midpoint of the segment is the mean
# of the distances of the end points
dist = 0.5 * (ds.dNode.isel(nHorizNodes=segment) +
ds.dNode.isel(nHorizNodes=segment + 1))
dist_cell[icell] += dist
count_cell[icell] += 1
dist_edge[iedge] += dist
count_edge[iedge] += 1

mask = count_cell > 0
dist_cell[mask] /= count_cell[mask]
dist_cell[np.logical_not(mask)] = np.nan

mask = count_edge > 0
dist_edge[mask] /= count_edge[mask]
dist_edge[np.logical_not(mask)] = np.nan

ds['transectDistanceCell'] = ('nCells', dist_cell)
ds['transectDistanceEdge'] = ('nEdges', dist_edge)
logger.info('Done.')
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, this part is the important new addition.

The transect module is just here because the version in Polaris (which this is a copy of) is cleaner than the version in MPAS-Tools but we don't have a way to use it in QuickViz because Polaris isn't a simple conda package that can be installed from conda-forge.

@alicebarthel
Copy link
Collaborator

yes, @milenaveneziani I did a first-order analysis by combining the Antarctic shelf regions and using the openBoundaries script. Ordering the edges by longitude was not completely clean around the peninsula, and I wanted to expand the analysis to plot by distance along the edge. In addition, I had to check that the recombining of regions is continuous across the 2 resolutions (LR and SORRM) I've done analysis over. @xylar offered to develop this transect (PR#202) to have a reference 1000-m circum-Antarctic transect, with the distance calculated using the existing tools.
From today's conversation, @xylar suggested adding the relevant circum-Antarctic shelf regionmask too. I think that will be great to have, esp. with it being neatly consistent with the transect.

@milenaveneziani
Copy link
Collaborator

Thank you both. This is great. I think the reason why you still need to go through MpasMaskCreator is that that tool gives you sorted edges (from point A to B): is that correct?
And yes: having a circumantarctic transect along the shelf sounds great. I would go further and make it into the offshore boundary of a circumantarctic shelf region. So, basically adding two features in geometric_features.

@xylar
Copy link
Collaborator Author

xylar commented Jun 5, 2024

@milenaveneziani, yes, we also decided that a feature defining the enclosed region would be useful and I did that in:
MPAS-Dev/geometric_features#202

@alicebarthel and @cbegeman, I made the requested changes to MPAS-Dev/geometric_features#202.

I will add a script tomorrow that can be used to cut out a square from a closed-loop transect (centered at a given lat/lon and with a given size). I'm too tired to do that tonight even though I wanted to keep the momentum going...

@xylar xylar force-pushed the add-transect-with-edge-sign-and-distance branch from 75eb688 to ab0f76d Compare June 6, 2024 13:46
@xylar
Copy link
Collaborator Author

xylar commented Jun 6, 2024

Okay, I added the tool for cutting the loop, as promised. The updated instructions to replace the last step in are:

./cut_closed_transect.py -f "Antarctic 1000m isobath" --lat -65.91 --lon 80.38 --size 0.1 -o cut_Antarctic_1000m_isobath.geojson
./create_transect_masks.py -m SOwISC12to60E2r4.230314.nc -g cut_Antarctic_1000m_isobath.geojson -o SOwISC12to60E2r4_Antarctic_1000m_isobath.nc --process_count 4

the instructions before that are all the same.

You may also want to look at the resulting fields in paraview:

 paraview_vtk_field_extractor.py -v all -m SOwISC12to60E2r4.230314.nc -f SOwISC12to60E2r4_Antarctic_1000m_isobath.nc --ignore_time -d nTransects=0
paraview vtk_files/staticFieldsOnEdges.vtp

distance_edges

@xylar
Copy link
Collaborator Author

xylar commented Jun 6, 2024

@alicebarthel, could you test this out on the meshes you plan to analyze (in particular the LR mesh)? It would be important to know if there are gaps in the transect, following @milenaveneziani's concerns. Even if so, we might be okay with that since these are presumably places where there simply isn't any continental shelf according to the model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants