├── .github ├── dependabot.yml └── workflows │ ├── build_workflow.yml │ ├── docs_workflow.yml │ └── pre_commit_update_workflow.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CITATION.cff ├── LICENSE ├── README.md ├── atmosphere └── README ├── conda_package ├── .gitignore ├── MANIFEST.in ├── ci │ ├── linux_64_python3.10.____cpython.yaml │ ├── linux_64_python3.11.____cpython.yaml │ ├── linux_64_python3.12.____cpython.yaml │ ├── linux_64_python3.13.____cpython.yaml │ ├── linux_64_python3.9.____cpython.yaml │ ├── osx_64_python3.10.____cpython.yaml │ ├── osx_64_python3.11.____cpython.yaml │ ├── osx_64_python3.12.____cpython.yaml │ ├── osx_64_python3.13.____cpython.yaml │ └── osx_64_python3.9.____cpython.yaml ├── dev-spec.txt ├── docs │ ├── .gitignore │ ├── Makefile │ ├── _static │ │ └── style.css │ ├── _templates │ │ └── layout.html │ ├── api.rst │ ├── authors.rst │ ├── building_docs.rst │ ├── cime.rst │ ├── conf.py │ ├── config.rst │ ├── generate_versions_json.py │ ├── images │ │ ├── ais_map.png │ │ ├── ais_map_with_grounding_lines.png │ │ ├── ais_thickness_change_map.png │ │ ├── clipped.png │ │ ├── ec60to30_tris_flat.png │ │ ├── ec60to30_tris_gouraud.png │ │ ├── qu240_topo.png │ │ ├── qu240_topo_lonlat.png │ │ ├── ragged.png │ │ ├── so60to10.png │ │ ├── so60to12_res.png │ │ ├── so_cropped.png │ │ ├── south_atlantic_temperature_transect.png │ │ ├── thwaites_temperature_transects.png │ │ └── thwaites_transect.png │ ├── index.rst │ ├── interpolation.rst │ ├── io.rst │ ├── landice │ │ └── visualization.rst │ ├── logging.rst │ ├── making_changes.rst │ ├── mesh_conversion.rst │ ├── mesh_creation.rst │ ├── mpas_to_xdmf.rst │ ├── ocean │ │ ├── coastal_tools.rst │ │ ├── coastline_alteration.rst │ │ ├── depth.rst │ │ ├── mesh_creation.rst │ │ ├── moc.rst │ │ ├── streamfunction.rst │ │ └── visualization.rst │ ├── paraview_extractor.rst │ ├── seaice │ │ ├── mask.rst │ │ ├── mesh.rst │ │ ├── partition.rst │ │ ├── regions.rst │ │ └── regrid.rst │ ├── shared │ │ └── version-switcher.js │ ├── testing_changes.rst │ ├── transects.rst │ ├── vector.rst │ └── visualization.rst ├── mpas_tools │ ├── __init__.py │ ├── __main__.py │ ├── cime │ │ ├── __init__.py │ │ └── constants.py │ ├── config.py │ ├── conversion.py │ ├── io.py │ ├── landice │ │ ├── __init__.py │ │ ├── boundary.py │ │ ├── create.py │ │ ├── cull.py │ │ ├── interpolate.py │ │ ├── projections.py │ │ └── visualization.py │ ├── logging.py │ ├── merge_grids.py │ ├── mesh │ │ ├── __init__.py │ │ ├── conversion.py │ │ ├── creation │ │ │ ├── __init__.py │ │ │ ├── build_mesh.py │ │ │ ├── jigsaw_driver.py │ │ │ ├── jigsaw_to_netcdf.py │ │ │ ├── mesh_definition_tools.py │ │ │ ├── mpas_to_triangle.py │ │ │ ├── open_msh.py │ │ │ ├── signed_distance.py │ │ │ ├── sort_mesh.py │ │ │ ├── triangle_to_netcdf.py │ │ │ └── util.py │ │ ├── cull.py │ │ ├── interpolation.py │ │ ├── mark_horns_for_culling.py │ │ ├── mask.py │ │ └── set_lat_lon.py │ ├── ocean │ │ ├── __init__.py │ │ ├── barotropic_streamfunction.py │ │ ├── build_mesh.py │ │ ├── coastal_tools.py │ │ ├── coastline_alteration.py │ │ ├── depth.py │ │ ├── inject_bathymetry.py │ │ ├── inject_meshDensity.py │ │ ├── inject_preserve_floodplain.py │ │ ├── moc.py │ │ └── viz │ │ │ ├── __init__.py │ │ │ ├── inset.py │ │ │ └── transect │ │ │ ├── __init__.py │ │ │ ├── plot.py │ │ │ └── vert.py │ ├── parallel.py │ ├── planar_hex.py │ ├── scrip │ │ ├── __init__.py │ │ ├── from_mpas.py │ │ └── from_planar.py │ ├── seaice │ │ ├── __init__.py │ │ ├── mask.py │ │ ├── mesh.py │ │ ├── partition.py │ │ ├── regions.py │ │ └── regrid.py │ ├── split_grids.py │ ├── transects.py │ ├── translate.py │ ├── vector │ │ ├── __init__.py │ │ └── reconstruct.py │ └── viz │ │ ├── SciVisColorColormaps │ │ ├── 3Wbgy5.xml │ │ ├── 3wave-yellow-grey-blue.xml │ │ ├── 4wave-grey-red-green-mgreen.xml │ │ ├── 5wave-yellow-brown-blue.xml │ │ ├── Publications.bib │ │ ├── __init__.py │ │ ├── blue-1.xml │ │ ├── blue-3.xml │ │ ├── blue-6.xml │ │ ├── blue-8.xml │ │ ├── blue-orange-div.xml │ │ ├── brown-2.xml │ │ ├── brown-5.xml │ │ ├── brown-8.xml │ │ ├── green-1.xml │ │ ├── green-4.xml │ │ ├── green-7.xml │ │ ├── green-8.xml │ │ ├── orange-5.xml │ │ ├── orange-6.xml │ │ ├── orange-green-blue-gray.xml │ │ ├── purple-7.xml │ │ ├── purple-8.xml │ │ ├── red-1.xml │ │ ├── red-3.xml │ │ ├── red-4.xml │ │ ├── yellow-1.xml │ │ └── yellow-7.xml │ │ ├── __init__.py │ │ ├── colormaps.py │ │ ├── mesh_to_triangles.py │ │ ├── mpas_to_xdmf │ │ ├── __init__.py │ │ ├── geometry.py │ │ ├── io.py │ │ ├── mesh.py │ │ ├── mpas_to_xdmf.py │ │ ├── templates │ │ │ ├── __init__.py │ │ │ └── xdmf_template.xml │ │ └── time.py │ │ ├── paraview_extractor.py │ │ └── transect │ │ ├── __init__.py │ │ └── horiz.py ├── pyproject.toml ├── recipe │ ├── build.sh │ └── meta.yaml └── tests │ ├── __init__.py │ ├── test_cime_constants.py │ ├── test_conversion.py │ ├── test_depth.py │ ├── test_io.py │ ├── test_mesh_creation_util.py │ ├── test_mesh_mask.py │ ├── test_signed_distance.py │ ├── test_transects.py │ ├── test_viz_transects.py │ ├── test_viz_xdmf.py │ └── util.py ├── landice ├── mesh_tools_li │ ├── ISMIP6-2500_Forcing.py │ ├── add_no_water_flux_around_boundary.py │ ├── adjust_iceshelf_geometry.py │ ├── adjust_thickness_at_false_ocean_cells.py │ ├── bulldoze_missing_troughs.py │ ├── conversion_exodus_init_to_mpasli_mesh.py │ ├── extrapolate_variable.py │ ├── flood_fill_thawed_ice.py │ ├── misc │ │ ├── README_grid_generation_workflow.txt │ │ ├── calibrate_beta.py │ │ ├── copy_etopo_to_MPAS_sphere_grid.py │ │ ├── mpas_mesh_to_landice_ic_batch.sh │ │ └── prepare_pattyn_temperature_field_for_interpolation.m │ ├── set_von_mises_stress_map.py │ └── tune_ismip6_melt_deltat.py └── output_processing_li │ ├── convert_landice_bitmasks.py │ ├── ismip6_postprocessing │ ├── create_mapfile_mali_to_ismip6.py │ ├── post_process_mali_to_ismip6.py │ ├── process_flux_variables.py │ ├── process_state_variables.py │ └── recalculate_missing_2d_state_vars.py │ ├── plot_calving_calibration.py │ ├── plot_globalStats.py │ ├── plot_maps.py │ ├── plot_mass_balance.py │ ├── plot_regionalStats.py │ ├── plot_transect.py │ └── remove_output_file_time_loops.py ├── mesh_tools ├── create_SCRIP_files │ └── create_scrip_mask_for_sufficiently_deep_ocean_mapping.py ├── grid_rotate │ ├── Makefile │ ├── README │ ├── grid_rotate.f90 │ ├── mesh.ncl │ └── namelist.input ├── hex_projection │ ├── Makefile │ ├── README │ ├── mesh_boundary_plot.py │ ├── mesh_plot.ncl │ ├── mpas_geometry_utilities.f90 │ ├── namelist.projections │ ├── ph_utils.f90 │ ├── ph_write_mesh.f90 │ ├── precision.f90 │ ├── project_hexes.f90 │ ├── projection_setup.f90 │ └── projections.f90 ├── merge_split_meshes │ ├── merge_grids.py │ └── split_grids.py ├── mesh_conversion_tools │ ├── CMakeLists.txt │ ├── Makefile │ ├── README │ ├── edge.h │ ├── json │ │ ├── json-forwards.h │ │ └── json.h │ ├── jsoncpp.cpp │ ├── mpas_cell_culler.cpp │ ├── mpas_mask_creator.cpp │ ├── mpas_mesh_converter.cpp │ ├── netcdf-cxx-4.2 │ │ ├── COPYRIGHT │ │ ├── README │ │ ├── config.h │ │ ├── ncvalues.cpp │ │ ├── ncvalues.h │ │ ├── netcdf.cpp │ │ ├── netcdf.hh │ │ └── netcdfcpp.h │ ├── netcdf_utils.cpp │ ├── netcdf_utils.h │ ├── pnt.h │ ├── string_utils.h │ └── test │ │ ├── Arctic_Ocean.geojson │ │ ├── land_mask_final.nc │ │ └── mesh.QU.1920km.151026.nc ├── mesh_conversion_tools_netcdf_c │ ├── CMakeLists.txt │ ├── README │ ├── edge.h │ ├── json │ │ ├── json-forwards.h │ │ └── json.h │ ├── jsoncpp.cpp │ ├── mpas_cell_culler.cpp │ ├── mpas_mesh_converter.cpp │ ├── netcdf_utils.h │ ├── pnt.h │ └── string_utils.h ├── mpas2esmf │ ├── .gitignore │ ├── Makefile │ ├── README.md │ └── mpas2esmf.f90 ├── periodic_hex │ ├── Makefile │ ├── cells.ncl │ ├── mark_periodic_boundaries_for_culling.py │ ├── module_cell_indexing.F │ ├── module_write_netcdf.F │ ├── namelist.input │ └── periodic_grid.F ├── periodic_quad │ ├── Makefile │ ├── cells.ncl │ ├── module_cell_indexing.F │ ├── module_write_netcdf.F │ ├── namelist.input │ └── periodic_grid.F ├── planar_grid_transformations │ ├── multires_scaled_hex.py │ ├── rotate_planar_grid.readme.txt │ ├── scale_planar_grid.py │ └── translate_planar_grid.py ├── planar_hex │ ├── mpas_tools │ └── planar_hex ├── points-mpas │ ├── .gitignore │ ├── Makefile │ ├── Params │ ├── README │ ├── SaveDensity │ ├── SaveTriangles │ ├── SaveVertices │ ├── points-mpas.cpp │ └── triangulation.h ├── processor_decompositions │ ├── README │ └── make_partition_files.py └── seaice_grid_tools │ ├── CMakeLists.txt │ ├── Makefile │ ├── README │ ├── cmake │ ├── FindNetCDF.cmake │ ├── LICENSE │ └── README │ ├── create_seaice_partitions.py │ ├── cull_equatorial_region.py │ ├── extend_seaice_mask.py │ ├── fix_regrid_output.F90 │ ├── gen_seaice_mesh_partition.py │ ├── gen_seaice_regions_latitude_bands.py │ ├── make_regions_file.py │ ├── mpas_tools │ ├── prepare_seaice_partitions.py │ ├── regrid_to_other_mesh.py │ ├── rescale_mesh.py │ └── seaice_mesh.py ├── ocean ├── coastline_alteration │ ├── add_critical_land_blockages_to_mask.py │ ├── add_land_locked_cells_to_mask.py │ ├── mpas_tools │ └── widen_transect_edge_masks.py ├── initial_condition_interpolation │ └── interpolate_state.py ├── moc_southern_boundary_extractor │ ├── moc_southern_boundary_extractor.py │ └── mpas_tools ├── performance_testing │ ├── README │ ├── performance_test.py │ ├── plot_from_files.py │ ├── submit_performance_test_to_queue.py │ └── weights │ │ ├── call_to_performance_testing.py │ │ ├── generate_graph.info_with_wgts.py │ │ └── performance_testing.py └── smooth_topo │ ├── CMakeLists.txt │ ├── README │ ├── cmake │ ├── FindNetCDF.cmake │ ├── LICENSE │ └── README │ ├── smooth_topo_before_init.F90 │ ├── smooth_topo_before_init_skip_land_ice.F90 │ └── smooth_topo_skip_land_ice.F90 ├── operators ├── mpas_tools └── vector_reconstruction.py ├── output_processing ├── decomposition_fields │ ├── README │ └── decomposition_fields.py └── grid_quality │ ├── README │ └── grid_quality.py ├── seaice └── README ├── source_code_processing ├── e3sm_namelist_file_generator │ └── generate_e3sm_namelist_files.py └── mpas_source_linter │ └── mpas_source_linter.py └── visualization ├── e3sm_cpl_field_conversion └── extract_mpas_cpl_fields.sh ├── mpas_draw ├── .gitignore ├── MATPLOTLIB_LICENSE ├── Makefile ├── README ├── constants.h ├── mpas_draw.cpp ├── netcdf_utils.cpp ├── netcdf_utils.h ├── vec_utils.cpp └── vec_utils.h ├── paraview_vtk_field_extractor ├── add_earth_sphere.py ├── annotate_date.py ├── mpas_tools └── paraview_vtk_field_extractor.py └── planar_grids ├── convert_mpas_grid_to_regular_grid_netcdf.py ├── plot_mpas_field.py ├── plot_mpas_field_xsect.py ├── plot_mpas_velocity_on_edges.py └── visualize_blocks.py /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | 5 | - package-ecosystem: "github-actions" 6 | directory: "/" 7 | schedule: 8 | interval: "weekly" 9 | assignees: 10 | - "xylar" 11 | reviewers: 12 | - "xylar" 13 | - "altheaden" 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/pre_commit_update_workflow.yml: -------------------------------------------------------------------------------- 1 | name: Pre-commit auto-update 2 | 3 | on: 4 | schedule: 5 | # Cron syntax: 6 | # 1. Entry: Minute when the process will be started [0-60] 7 | # 2. Entry: Hour when the process will be started [0-23] 8 | # 3. Entry: Day of the month when the process will be started [1-28/29/30/31] 9 | # 4. Entry: Month of the year when the process will be started [1-12] 10 | # 5. Entry: Weekday when the process will be started [0-6] [0 is Sunday] 11 | - cron: '0 8 * * 3' 12 | 13 | env: 14 | UP_TO_DATE: false 15 | PYTHON_VERSION: "3.10" 16 | 17 | jobs: 18 | auto-update: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | 23 | - name: Set up Python 24 | uses: actions/setup-python@v5 25 | with: 26 | python-version: ${{ env.PYTHON_VERSION }} 27 | 28 | - name: Install pre-commit 29 | run: pip install pre-commit 30 | 31 | - name: Apply and commit updates 32 | run: | 33 | git clone https://github.com/MPAS-Dev/MPAS-Tools.git update-pre-commit-deps 34 | cd update-pre-commit-deps 35 | # Configure git using GitHub Actions credentials. 36 | git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" 37 | git config --local user.name "github-actions[bot]" 38 | git checkout -b update-pre-commit-deps 39 | pre-commit autoupdate 40 | git add . 41 | # The second command will fail if no changes were present, so we ignore it 42 | git commit -m "Update pre-commit dependencies" || ( echo "UP_TO_DATE=true" >> "$GITHUB_ENV") 43 | 44 | - name: Push Changes 45 | if: ${{ env.UP_TO_DATE == 'false' }} 46 | uses: ad-m/github-push-action@master 47 | with: 48 | branch: update-pre-commit-deps 49 | directory: update-pre-commit-deps 50 | github_token: ${{ secrets.GITHUB_TOKEN }} 51 | force: true 52 | env: 53 | GH_TOKEN: ${{ github.token }} 54 | 55 | - name: Make PR and add reviewers and labels 56 | if: ${{ env.UP_TO_DATE == 'false' }} 57 | run: | 58 | cd update-pre-commit-deps 59 | gh pr create \ 60 | --title "Update pre-commit and its dependencies" \ 61 | --body "This PR was auto-generated to update pre-commit and its dependencies." \ 62 | --head update-pre-commit-deps \ 63 | --reviewer altheaden,xylar \ 64 | --label ci 65 | env: 66 | GH_TOKEN: ${{ github.token }} 67 | 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all netcdf files and graph files 2 | *.nc 3 | *.info 4 | *.info.part.* 5 | *.o 6 | *.mod 7 | 8 | # Ignore all PNGs 9 | *.png 10 | 11 | # Each tool should also have it's own .gitignore file that ignores the build files for that tool. 12 | 13 | # Byte-compiled / optimized / DLL files 14 | __pycache__/ 15 | *.py[cod] 16 | *$py.class 17 | 18 | # C extensions 19 | *.so 20 | 21 | # Distribution / packaging 22 | .Python 23 | env/ 24 | build/ 25 | develop-eggs/ 26 | dist/ 27 | downloads/ 28 | eggs/ 29 | .eggs/ 30 | lib/ 31 | lib64/ 32 | parts/ 33 | sdist/ 34 | var/ 35 | *.egg-info/ 36 | .installed.cfg 37 | *.egg 38 | 39 | # PyInstaller 40 | # Usually these files are written by a python script from a template 41 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 42 | *.manifest 43 | *.spec 44 | 45 | # Installer logs 46 | pip-log.txt 47 | pip-delete-this-directory.txt 48 | 49 | # Unit test / coverage reports 50 | htmlcov/ 51 | .tox/ 52 | .coverage 53 | .coverage.* 54 | .cache 55 | nosetests.xml 56 | coverage.xml 57 | *,cover 58 | .hypothesis/ 59 | 60 | # Translations 61 | *.mo 62 | *.pot 63 | 64 | # Django stuff: 65 | *.log 66 | local_settings.py 67 | 68 | # Flask stuff: 69 | instance/ 70 | .webassets-cache 71 | 72 | # Scrapy stuff: 73 | .scrapy 74 | 75 | # Sphinx documentation 76 | docs/_build/ 77 | 78 | # PyBuilder 79 | target/ 80 | 81 | # IPython Notebook 82 | .ipynb_checkpoints 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # celery beat schedule file 88 | celerybeat-schedule 89 | 90 | # dotenv 91 | .env 92 | 93 | # virtualenv 94 | venv/ 95 | ENV/ 96 | 97 | # Spyder project settings 98 | .spyderproject 99 | 100 | # Rope project settings 101 | .ropeproject 102 | 103 | .DS_Store 104 | 105 | # pycharm 106 | .idea 107 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | files: "conda_package" 2 | default_stages: [pre-commit] 3 | fail_fast: true 4 | 5 | repos: 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v5.0.0 8 | hooks: 9 | - id: trailing-whitespace 10 | - id: end-of-file-fixer 11 | 12 | # Can run individually with `flynt [file]` or `flynt [source]` 13 | - repo: https://github.com/ikamensh/flynt 14 | rev: '1.0.1' 15 | hooks: 16 | - id: flynt 17 | args: ["--fail-on-change", "--verbose"] 18 | require_serial: true 19 | 20 | - repo: https://github.com/astral-sh/ruff-pre-commit 21 | rev: v0.11.12 22 | hooks: 23 | # Sort the imports 24 | - id: ruff 25 | name: ruff-sort-imports 26 | args: [--select, I, --fix] 27 | # Run the linter. 28 | - id: ruff 29 | args: [--fix] 30 | # Run the formatter. 31 | - id: ruff-format 32 | 33 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | # This CITATION.cff file was generated with cffinit. 2 | # Visit https://bit.ly/cffinit to generate yours today! 3 | 4 | cff-version: 1.2.0 5 | title: MPAS-Tools 6 | message: >- 7 | If you use this software, please cite it using the 8 | metadata from this file. 9 | type: software 10 | authors: 11 | - given-names: Douglas 12 | family-names: Jacobsen 13 | orcid: 'https://orcid.org/0000-0002-3836-207X' 14 | - given-names: Michael 15 | family-names: Duda 16 | orcid: 'https://orcid.org/0009-0003-8376-5147' 17 | - given-names: Xylar 18 | family-names: Asay-Davis 19 | orcid: 'https://orcid.org/0000-0002-1990-892X' 20 | email: xylar@lanl.gov 21 | - given-names: Matthew 22 | family-names: Hoffman 23 | orcid: 'https://orcid.org/0000-0001-5076-0540' 24 | - given-names: Mark 25 | family-names: Petersen 26 | orcid: 'https://orcid.org/0000-0001-7170-7511' 27 | - given-names: William 28 | family-names: Skamarock 29 | orcid: 'https://orcid.org/0000-0002-6667-2446' 30 | - orcid: 'https://orcid.org/0000-0001-5971-4241' 31 | given-names: Phillip 32 | family-names: Wolfram 33 | - orcid: 'https://orcid.org/0000-0003-3535-1540' 34 | given-names: Trevor 35 | family-names: Hillebrand 36 | - given-names: Holly 37 | family-names: Han 38 | orcid: 'https://orcid.org/0000-0002-3819-5275' 39 | - given-names: Joseph 40 | family-names: Kennedy 41 | orcid: 'https://orcid.org/0000-0002-9348-693X' 42 | - given-names: Adrian 43 | family-names: Turner 44 | orcid: 'https://orcid.org/0000-0001-6796-4187' 45 | - given-names: Miles 46 | family-names: Curry 47 | - given-names: Todd 48 | family-names: Ringler 49 | orcid: 'https://orcid.org/0000-0003-4433-4320' 50 | - given-names: Stephen 51 | family-names: Price 52 | orcid: 'https://orcid.org/0000-0001-6878-2553' 53 | - given-names: Tong 54 | family-names: Zhang 55 | - given-names: Althea 56 | family-names: Denlinger 57 | - given-names: Darren 58 | family-names: Engwirda 59 | orcid: 'https://orcid.org/0000-0002-3379-9109' 60 | - given-names: Alex 61 | family-names: Hager 62 | - orcid: 'https://orcid.org/0000-0001-9828-1741' 63 | given-names: Carolyn 64 | family-names: Begeman 65 | - given-names: Andrew 66 | family-names: Nolan 67 | orcid: 'https://orcid.org/0000-0002-9785-0196' 68 | - family-names: Saenz 69 | given-names: Juan 70 | - given-names: Maciej 71 | family-names: Waruszewski 72 | - given-names: Dominikus 73 | family-names: Heinzeller 74 | orcid: 'https://orcid.org/0000-0003-2962-1049' 75 | - given-names: Cameron 76 | family-names: Smith 77 | repository-code: 'https://github.com/MPAS-Dev/MPAS-Tools' 78 | url: 'https://mpas-dev.github.io/MPAS-Tools/master/' 79 | version: 1.2.0 80 | date-released: '2025-06-06' 81 | 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2020, Los Alamos National Security, LLC (LANS) (Ocean: LA-CC-13-047; 2 | Land Ice: LA-CC-13-117) and the University Corporation for Atmospheric Research (UCAR). 3 | 4 | All rights reserved. 5 | 6 | LANS is the operator of the Los Alamos National Laboratory under Contract No. 7 | DE-AC52-06NA25396 with the U.S. Department of Energy. UCAR manages the National 8 | Center for Atmospheric Research under Cooperative Agreement ATM-0753581 with the 9 | National Science Foundation. The U.S. Government has rights to use, reproduce, 10 | and distribute this software. NO WARRANTY, EXPRESS OR IMPLIED IS OFFERED BY 11 | LANS, UCAR OR THE GOVERNMENT AND NONE OF THEM ASSUME ANY LIABILITY FOR THE USE 12 | OF THIS SOFTWARE. If software is modified to produce derivative works, such 13 | modified software should be clearly marked, so as not to confuse it with the 14 | version available from LANS and UCAR. 15 | 16 | Additionally, redistribution and use in source and binary forms, with or without 17 | modification, are permitted provided that the following conditions are met: 18 | 19 | 1) Redistributions of source code must retain the above copyright notice, this 20 | list of conditions and the following disclaimer. 21 | 22 | 2) Redistributions in binary form must reproduce the above copyright notice, 23 | this list of conditions and the following disclaimer in the documentation and/or 24 | other materials provided with the distribution. 25 | 26 | 3) None of the names of LANS, UCAR or the names of its contributors, if any, may 27 | be used to endorse or promote products derived from this software without 28 | specific prior written permission. 29 | 30 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 31 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 32 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 33 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 34 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 35 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 36 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 37 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 39 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MPAS Tools 2 | 3 | This repository houses all MPAS related tools. These include compiled tools, 4 | and scripts with a variety of purposes. Tools should be sorted into larger 5 | directories based on their purpose. Under each of these directories, a tool 6 | should live in it's own directory. 7 | 8 | ## Documentation 9 | 10 | The latest documentation for the conda package `mpas-tools` can be found here: 11 | 12 | [http://mpas-dev.github.io/MPAS-Tools/master/](http://mpas-dev.github.io/MPAS-Tools/master/) 13 | 14 | Many tools are not in the conda package, and documentation (sometimes fairly 15 | limited) is available at the beginning of each script. 16 | -------------------------------------------------------------------------------- /atmosphere/README: -------------------------------------------------------------------------------- 1 | Readme file for MPAS-Tools atmosphere directory. 2 | -------------------------------------------------------------------------------- /conda_package/.gitignore: -------------------------------------------------------------------------------- 1 | # Files created by "python -m pip install -e ." 2 | /landice/ 3 | /mesh_tools/ 4 | /ocean/ 5 | /visualization/ 6 | -------------------------------------------------------------------------------- /conda_package/MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include mpas_tools *.xml 2 | -------------------------------------------------------------------------------- /conda_package/ci/linux_64_python3.10.____cpython.yaml: -------------------------------------------------------------------------------- 1 | c_stdlib: 2 | - sysroot 3 | c_stdlib_version: 4 | - '2.17' 5 | cdt_name: 6 | - conda 7 | channel_sources: 8 | - conda-forge 9 | channel_targets: 10 | - conda-forge main 11 | cxx_compiler: 12 | - gxx 13 | cxx_compiler_version: 14 | - '13' 15 | docker_image: 16 | - quay.io/condaforge/linux-anvil-cos7-x86_64 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | netcdf_fortran: 26 | - '4.6' 27 | pin_run_as_build: 28 | python: 29 | min_pin: x.x 30 | max_pin: x.x 31 | python: 32 | - 3.10.* *_cpython 33 | target_platform: 34 | - linux-64 35 | zip_keys: 36 | - - cxx_compiler_version 37 | - fortran_compiler_version 38 | -------------------------------------------------------------------------------- /conda_package/ci/linux_64_python3.11.____cpython.yaml: -------------------------------------------------------------------------------- 1 | c_stdlib: 2 | - sysroot 3 | c_stdlib_version: 4 | - '2.17' 5 | cdt_name: 6 | - conda 7 | channel_sources: 8 | - conda-forge 9 | channel_targets: 10 | - conda-forge main 11 | cxx_compiler: 12 | - gxx 13 | cxx_compiler_version: 14 | - '13' 15 | docker_image: 16 | - quay.io/condaforge/linux-anvil-cos7-x86_64 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | netcdf_fortran: 26 | - '4.6' 27 | pin_run_as_build: 28 | python: 29 | min_pin: x.x 30 | max_pin: x.x 31 | python: 32 | - 3.11.* *_cpython 33 | target_platform: 34 | - linux-64 35 | zip_keys: 36 | - - cxx_compiler_version 37 | - fortran_compiler_version 38 | -------------------------------------------------------------------------------- /conda_package/ci/linux_64_python3.12.____cpython.yaml: -------------------------------------------------------------------------------- 1 | c_stdlib: 2 | - sysroot 3 | c_stdlib_version: 4 | - '2.17' 5 | cdt_name: 6 | - conda 7 | channel_sources: 8 | - conda-forge 9 | channel_targets: 10 | - conda-forge main 11 | cxx_compiler: 12 | - gxx 13 | cxx_compiler_version: 14 | - '13' 15 | docker_image: 16 | - quay.io/condaforge/linux-anvil-cos7-x86_64 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | netcdf_fortran: 26 | - '4.6' 27 | pin_run_as_build: 28 | python: 29 | min_pin: x.x 30 | max_pin: x.x 31 | python: 32 | - 3.12.* *_cpython 33 | target_platform: 34 | - linux-64 35 | zip_keys: 36 | - - cxx_compiler_version 37 | - fortran_compiler_version 38 | -------------------------------------------------------------------------------- /conda_package/ci/linux_64_python3.13.____cpython.yaml: -------------------------------------------------------------------------------- 1 | c_stdlib: 2 | - sysroot 3 | c_stdlib_version: 4 | - '2.17' 5 | cdt_name: 6 | - conda 7 | channel_sources: 8 | - conda-forge 9 | channel_targets: 10 | - conda-forge main 11 | cxx_compiler: 12 | - gxx 13 | cxx_compiler_version: 14 | - '13' 15 | docker_image: 16 | - quay.io/condaforge/linux-anvil-cos7-x86_64 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | netcdf_fortran: 26 | - '4.6' 27 | pin_run_as_build: 28 | python: 29 | min_pin: x.x 30 | max_pin: x.x 31 | python: 32 | - 3.13.* *_cp313 33 | target_platform: 34 | - linux-64 35 | zip_keys: 36 | - - cxx_compiler_version 37 | - fortran_compiler_version 38 | -------------------------------------------------------------------------------- /conda_package/ci/linux_64_python3.9.____cpython.yaml: -------------------------------------------------------------------------------- 1 | c_stdlib: 2 | - sysroot 3 | c_stdlib_version: 4 | - '2.17' 5 | cdt_name: 6 | - conda 7 | channel_sources: 8 | - conda-forge 9 | channel_targets: 10 | - conda-forge main 11 | cxx_compiler: 12 | - gxx 13 | cxx_compiler_version: 14 | - '13' 15 | docker_image: 16 | - quay.io/condaforge/linux-anvil-cos7-x86_64 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | netcdf_fortran: 26 | - '4.6' 27 | pin_run_as_build: 28 | python: 29 | min_pin: x.x 30 | max_pin: x.x 31 | python: 32 | - 3.9.* *_cpython 33 | target_platform: 34 | - linux-64 35 | zip_keys: 36 | - - cxx_compiler_version 37 | - fortran_compiler_version 38 | -------------------------------------------------------------------------------- /conda_package/ci/osx_64_python3.10.____cpython.yaml: -------------------------------------------------------------------------------- 1 | MACOSX_DEPLOYMENT_TARGET: 2 | - '10.13' 3 | MACOSX_SDK_VERSION: 4 | - '10.13' 5 | c_stdlib: 6 | - macosx_deployment_target 7 | c_stdlib_version: 8 | - '10.13' 9 | channel_sources: 10 | - conda-forge 11 | channel_targets: 12 | - conda-forge main 13 | cxx_compiler: 14 | - clangxx 15 | cxx_compiler_version: 16 | - '18' 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | llvm_openmp: 26 | - '18' 27 | macos_machine: 28 | - x86_64-apple-darwin13.4.0 29 | netcdf_fortran: 30 | - '4.6' 31 | pin_run_as_build: 32 | python: 33 | min_pin: x.x 34 | max_pin: x.x 35 | python: 36 | - 3.10.* *_cpython 37 | target_platform: 38 | - osx-64 39 | zip_keys: 40 | - - cxx_compiler_version 41 | - fortran_compiler_version 42 | -------------------------------------------------------------------------------- /conda_package/ci/osx_64_python3.11.____cpython.yaml: -------------------------------------------------------------------------------- 1 | MACOSX_DEPLOYMENT_TARGET: 2 | - '10.13' 3 | MACOSX_SDK_VERSION: 4 | - '10.13' 5 | c_stdlib: 6 | - macosx_deployment_target 7 | c_stdlib_version: 8 | - '10.13' 9 | channel_sources: 10 | - conda-forge 11 | channel_targets: 12 | - conda-forge main 13 | cxx_compiler: 14 | - clangxx 15 | cxx_compiler_version: 16 | - '18' 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | llvm_openmp: 26 | - '18' 27 | macos_machine: 28 | - x86_64-apple-darwin13.4.0 29 | netcdf_fortran: 30 | - '4.6' 31 | pin_run_as_build: 32 | python: 33 | min_pin: x.x 34 | max_pin: x.x 35 | python: 36 | - 3.11.* *_cpython 37 | target_platform: 38 | - osx-64 39 | zip_keys: 40 | - - cxx_compiler_version 41 | - fortran_compiler_version 42 | -------------------------------------------------------------------------------- /conda_package/ci/osx_64_python3.12.____cpython.yaml: -------------------------------------------------------------------------------- 1 | MACOSX_DEPLOYMENT_TARGET: 2 | - '10.13' 3 | MACOSX_SDK_VERSION: 4 | - '10.13' 5 | c_stdlib: 6 | - macosx_deployment_target 7 | c_stdlib_version: 8 | - '10.13' 9 | channel_sources: 10 | - conda-forge 11 | channel_targets: 12 | - conda-forge main 13 | cxx_compiler: 14 | - clangxx 15 | cxx_compiler_version: 16 | - '18' 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | llvm_openmp: 26 | - '18' 27 | macos_machine: 28 | - x86_64-apple-darwin13.4.0 29 | netcdf_fortran: 30 | - '4.6' 31 | pin_run_as_build: 32 | python: 33 | min_pin: x.x 34 | max_pin: x.x 35 | python: 36 | - 3.12.* *_cpython 37 | target_platform: 38 | - osx-64 39 | zip_keys: 40 | - - cxx_compiler_version 41 | - fortran_compiler_version 42 | -------------------------------------------------------------------------------- /conda_package/ci/osx_64_python3.13.____cpython.yaml: -------------------------------------------------------------------------------- 1 | MACOSX_DEPLOYMENT_TARGET: 2 | - '10.13' 3 | MACOSX_SDK_VERSION: 4 | - '10.13' 5 | c_stdlib: 6 | - macosx_deployment_target 7 | c_stdlib_version: 8 | - '10.13' 9 | channel_sources: 10 | - conda-forge 11 | channel_targets: 12 | - conda-forge main 13 | cxx_compiler: 14 | - clangxx 15 | cxx_compiler_version: 16 | - '18' 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | llvm_openmp: 26 | - '18' 27 | macos_machine: 28 | - x86_64-apple-darwin13.4.0 29 | netcdf_fortran: 30 | - '4.6' 31 | pin_run_as_build: 32 | python: 33 | min_pin: x.x 34 | max_pin: x.x 35 | python: 36 | - 3.13.* *_cp313 37 | target_platform: 38 | - osx-64 39 | zip_keys: 40 | - - cxx_compiler_version 41 | - fortran_compiler_version 42 | -------------------------------------------------------------------------------- /conda_package/ci/osx_64_python3.9.____cpython.yaml: -------------------------------------------------------------------------------- 1 | MACOSX_DEPLOYMENT_TARGET: 2 | - '10.13' 3 | MACOSX_SDK_VERSION: 4 | - '10.13' 5 | c_stdlib: 6 | - macosx_deployment_target 7 | c_stdlib_version: 8 | - '10.13' 9 | channel_sources: 10 | - conda-forge 11 | channel_targets: 12 | - conda-forge main 13 | cxx_compiler: 14 | - clangxx 15 | cxx_compiler_version: 16 | - '18' 17 | fortran_compiler: 18 | - gfortran 19 | fortran_compiler_version: 20 | - '13' 21 | hdf5: 22 | - 1.14.4 23 | libnetcdf: 24 | - 4.9.2 25 | llvm_openmp: 26 | - '18' 27 | macos_machine: 28 | - x86_64-apple-darwin13.4.0 29 | netcdf_fortran: 30 | - '4.6' 31 | pin_run_as_build: 32 | python: 33 | min_pin: x.x 34 | max_pin: x.x 35 | python: 36 | - 3.9.* *_cpython 37 | target_platform: 38 | - osx-64 39 | zip_keys: 40 | - - cxx_compiler_version 41 | - fortran_compiler_version 42 | -------------------------------------------------------------------------------- /conda_package/dev-spec.txt: -------------------------------------------------------------------------------- 1 | # This file may be used to create an environment using: 2 | # $ conda create --name --file 3 | 4 | # Base 5 | python>=3.9 6 | cartopy 7 | cmocean 8 | dask 9 | geometric_features>=1.0.1,<2.0.0 10 | h5py 11 | hdf5 12 | inpoly 13 | libnetcdf 14 | matplotlib-base>=3.9.0 15 | nco 16 | netcdf4 17 | networkx 18 | numpy>=2.0,<3.0 19 | progressbar2 20 | pyamg 21 | pyevtk 22 | pyproj 23 | python-igraph 24 | scikit-image!=0.20.0 25 | scipy 26 | shapely>=2.0,<3.0 27 | tqdm 28 | xarray 29 | 30 | # Development 31 | flynt 32 | pip 33 | pre-commit 34 | pytest 35 | ruff 36 | setuptools 37 | 38 | # Documentation 39 | sphinx 40 | mock 41 | sphinx_rtd_theme 42 | -------------------------------------------------------------------------------- /conda_package/docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Files created by "python -m pip install -e ." 2 | /_build 3 | /generated 4 | -------------------------------------------------------------------------------- /conda_package/docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = mpas_tools 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Build into a versioned subdirectory 12 | versioned-html: 13 | @echo "Building version: $(DOCS_VERSION)" 14 | $(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html/$(DOCS_VERSION)" 15 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html/$(DOCS_VERSION)." 16 | @echo "Setting up shared version switcher for local preview..." 17 | mkdir -p _build/html/shared 18 | cp shared/version-switcher.js _build/html/shared/version-switcher.js 19 | python generate_versions_json.py --local 20 | 21 | # Override html target to include local setup 22 | html: 23 | $(SPHINXBUILD) -b html "$(SOURCEDIR)" "$(BUILDDIR)/html" 24 | @echo 25 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 26 | 27 | # Put it first so that "make" without argument is like "make help". 28 | help: 29 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 30 | 31 | 32 | clean: 33 | rm -rf generated 34 | @$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 35 | 36 | clean-versioned-html: 37 | rm -rf $(BUILDDIR)/html/* 38 | @echo "Cleaned versioned HTML builds." 39 | 40 | .PHONY: help Makefile 41 | 42 | # Catch-all target: route all unknown targets to Sphinx using the new 43 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 44 | %: Makefile 45 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 46 | -------------------------------------------------------------------------------- /conda_package/docs/_static/style.css: -------------------------------------------------------------------------------- 1 | .wy-nav-content { 2 | max-width: 1200px !important; 3 | } 4 | 5 | #version-switcher select { 6 | background-color: #2980b9; 7 | color: white; 8 | border: none; 9 | border-radius: 4px; 10 | padding: 4px 30px 4px 10px; 11 | font-size: 0.9em; 12 | appearance: none; /* Remove default dropdown arrow */ 13 | background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg fill='white' height='10' viewBox='0 0 24 24' width='10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E"); 14 | background-repeat: no-repeat; 15 | background-position: right 10px center; 16 | background-size: 12px; 17 | } 18 | 19 | #version-switcher select:focus { 20 | outline: none; 21 | box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.4); 22 | background-color: #2c89c4; /* slightly lighter blue on focus */ 23 | } 24 | 25 | /* Selected item in the dropdown menu */ 26 | #version-switcher option:checked { 27 | background-color: #dddddd; /* for selected */ 28 | color: black; 29 | } 30 | -------------------------------------------------------------------------------- /conda_package/docs/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | 3 | {% block extrahead %} 4 | 5 | {% endblock %} 6 | 7 | {% block footer %} 8 | {{ super() }} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 24 | 25 | 26 | 27 | {% endblock %} 28 | -------------------------------------------------------------------------------- /conda_package/docs/authors.rst: -------------------------------------------------------------------------------- 1 | Main Authors 2 | ============ 3 | * Xylar Asay-Davis 4 | * Michael Duda 5 | * Matthew Hoffman 6 | * Douglas Jacobsen 7 | 8 | Contributors 9 | ============ 10 | * Riley X. Brady 11 | * Miles Curry 12 | * Amrapalli Garanaik 13 | * Dom Heinzeller 14 | * Trevor Hillebrand 15 | * Joseph Kennedy 16 | * William Lipscomb 17 | * Mark Petersen 18 | * Stephen Price 19 | * Todd Ringler 20 | * Juan Saenz 21 | * Adrian Turner 22 | * Luke Van Roekel 23 | * Phillip J. Wolfram 24 | * Tong Zhang 25 | 26 | For a list of all the contributions: 27 | https://github.com/MPAS-Dev/MPAS-Tools/graphs/contributors 28 | -------------------------------------------------------------------------------- /conda_package/docs/building_docs.rst: -------------------------------------------------------------------------------- 1 | .. _dev_building_docs: 2 | 3 | ************************** 4 | Building the Documentation 5 | ************************** 6 | 7 | To make a local test build of the documentation, it is easiest to follow the 8 | :ref:`dev_testing_changes` procedure for how to make a local build of the 9 | ``mpas_tools`` package. The development environment includes the packages 10 | needed to build the documentation. Simply run: 11 | 12 | .. code-block:: bash 13 | 14 | cd conda_package/docs 15 | DOCS_VERSION=master make versioned-html 16 | 17 | **************************** 18 | Previewing the Documentation 19 | **************************** 20 | 21 | To preview the documentation locally, open the ``index.html`` file in the 22 | ``_build/html/master`` directory with your browser or try: 23 | 24 | .. code-block:: bash 25 | 26 | cd _build/html 27 | python -m http.server 8000 28 | 29 | Then, open http://0.0.0.0:8000/master/ in your browser. 30 | -------------------------------------------------------------------------------- /conda_package/docs/cime.rst: -------------------------------------------------------------------------------- 1 | .. _cime_mod: 2 | 3 | CIME Constants 4 | ============== 5 | 6 | The module :py:mod:`mpas_tools.cime.constants` contains constants that are in 7 | sync with `CIME `_, which provides infrastructure 8 | and utilities for Earth System Models such at E3SM. Currently, we sync only 9 | those constants given numerical values in CIME, not those that are derivied 10 | from other constants. Constants are checked against their values on CIME's 11 | master branch during tests of the conda build. 12 | 13 | Some of the constants most likely to be useful in MPAS-Tools, COMPASS and other 14 | related projects are: 15 | 16 | * ``SHR_CONST_CDAY`` - sec in calendar day (s) 17 | * ``SHR_CONST_REARTH`` - radius of Earth (m) 18 | * ``SHR_CONST_G`` - acceleration of gravity (m/s^2) 19 | * ``SHR_CONST_RHOFW`` - density of fresh water (kg/m^3) 20 | * ``SHR_CONST_RHOSW`` - density of sea water (kg/m^3) 21 | * ``SHR_CONST_RHOICE`` - density of ice (kg/m^3) 22 | * ``SHR_CONST_CPFW`` - specific heat of fresh water (J/kg/K) 23 | * ``SHR_CONST_CPSW`` - specific heat of sea water (J/kg/K) 24 | * ``SHR_CONST_CPICE`` - specific heat of fresh ice (J/kg/K) 25 | * ``SHR_CONST_LATICE`` - latent heat of fusion (J/kg) 26 | * ``SHR_CONST_LATVAP`` - latent heat of evaporation (J/kg) 27 | -------------------------------------------------------------------------------- /conda_package/docs/generate_versions_json.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import argparse 3 | import json 4 | import os 5 | import re 6 | 7 | 8 | def version_key(name): 9 | """Key function for sorting versions.""" 10 | match = re.match(r'^(\d+)\.(\d+)\.(\d+)$', name) 11 | if match: 12 | # Sort by major, minor, patch 13 | return tuple(map(int, match.groups())) 14 | return () 15 | 16 | 17 | # Mode: local or production 18 | parser = argparse.ArgumentParser( 19 | description='Generate versions.json for MPAS-Tools documentation.') 20 | parser.add_argument( 21 | '--local', 22 | action='store_true', 23 | help='Generate versions.json for local build.' 24 | ) 25 | args = parser.parse_args() 26 | local = args.local 27 | base_dir = '_build/html' if local else 'gh-pages' 28 | shared_dir = os.path.join(base_dir, 'shared') 29 | 30 | entries = [] 31 | 32 | if not os.path.exists(base_dir) or not os.listdir(base_dir): 33 | raise FileNotFoundError( 34 | f"Base directory '{base_dir}' does not exist or is empty.") 35 | 36 | versions = os.listdir(base_dir) 37 | numeric_versions = [] 38 | non_numeric_versions = [] 39 | 40 | for version in versions: 41 | # Check if it matches version pattern 42 | if re.match(r'^\d+\.\d+\.\d+$', version): 43 | numeric_versions.append(version) 44 | else: 45 | non_numeric_versions.append(version) 46 | 47 | # Sort numeric versions by major, minor, patch in descending order 48 | numeric_versions.sort(key=version_key, reverse=True) 49 | # Sort non-numeric versions alphabetically 50 | non_numeric_versions.sort() 51 | 52 | # Combine the sorted lists 53 | versions = non_numeric_versions + numeric_versions 54 | 55 | if 'master' in versions: 56 | versions.insert(0, versions.pop(versions.index('master'))) 57 | 58 | for name in versions: 59 | path = os.path.join(base_dir, name) 60 | if os.path.isdir(path) and name not in ('shared', '.git'): 61 | entries.append({ 62 | 'version': name, 63 | 'url': f'../{name}/' if local else f'/MPAS-Tools/{name}/' 64 | }) 65 | 66 | os.makedirs(shared_dir, exist_ok=True) 67 | with open(os.path.join(shared_dir, 'versions.json'), 'w') as f: 68 | json.dump(entries, f, indent=2) 69 | -------------------------------------------------------------------------------- /conda_package/docs/images/ais_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/ais_map.png -------------------------------------------------------------------------------- /conda_package/docs/images/ais_map_with_grounding_lines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/ais_map_with_grounding_lines.png -------------------------------------------------------------------------------- /conda_package/docs/images/ais_thickness_change_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/ais_thickness_change_map.png -------------------------------------------------------------------------------- /conda_package/docs/images/clipped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/clipped.png -------------------------------------------------------------------------------- /conda_package/docs/images/ec60to30_tris_flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/ec60to30_tris_flat.png -------------------------------------------------------------------------------- /conda_package/docs/images/ec60to30_tris_gouraud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/ec60to30_tris_gouraud.png -------------------------------------------------------------------------------- /conda_package/docs/images/qu240_topo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/qu240_topo.png -------------------------------------------------------------------------------- /conda_package/docs/images/qu240_topo_lonlat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/qu240_topo_lonlat.png -------------------------------------------------------------------------------- /conda_package/docs/images/ragged.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/ragged.png -------------------------------------------------------------------------------- /conda_package/docs/images/so60to10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/so60to10.png -------------------------------------------------------------------------------- /conda_package/docs/images/so60to12_res.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/so60to12_res.png -------------------------------------------------------------------------------- /conda_package/docs/images/so_cropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/so_cropped.png -------------------------------------------------------------------------------- /conda_package/docs/images/south_atlantic_temperature_transect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/south_atlantic_temperature_transect.png -------------------------------------------------------------------------------- /conda_package/docs/images/thwaites_temperature_transects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/thwaites_temperature_transects.png -------------------------------------------------------------------------------- /conda_package/docs/images/thwaites_transect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/docs/images/thwaites_transect.png -------------------------------------------------------------------------------- /conda_package/docs/index.rst: -------------------------------------------------------------------------------- 1 | MPAS-Tools 2 | ========== 3 | 4 | .. image:: images/so60to10.png 5 | :width: 500 px 6 | :align: center 7 | 8 | MPAS-Tools includes a python package, compiled Fortran, C and C++ tools, and 9 | scripts for supporting initialization, visualization and analysis of Model for 10 | Prediction Across Scales (MPAS) components. These tools are used by the 11 | `COMPASS `_ 12 | (Configuring of MPAS Setups) framework within 13 | `MPAS-Model `_ used to create 14 | ocean and land-ice test cases, 15 | the `MPAS-Analysis `_ package for 16 | analyzing simulations, and in other MPAS-related workflows. 17 | 18 | .. toctree:: 19 | :caption: User's Guide 20 | :maxdepth: 2 21 | 22 | mesh_creation 23 | mesh_conversion 24 | interpolation 25 | 26 | cime 27 | 28 | config 29 | 30 | io 31 | 32 | logging 33 | 34 | transects 35 | 36 | vector 37 | 38 | .. toctree:: 39 | :caption: Visualization 40 | :maxdepth: 2 41 | 42 | visualization 43 | mpas_to_xdmf 44 | paraview_extractor 45 | 46 | .. toctree:: 47 | :caption: Landice Tools 48 | :maxdepth: 2 49 | 50 | landice/visualization 51 | 52 | .. toctree:: 53 | :caption: Ocean Tools 54 | :maxdepth: 2 55 | 56 | ocean/mesh_creation 57 | ocean/coastal_tools 58 | ocean/coastline_alteration 59 | ocean/moc 60 | ocean/depth 61 | ocean/streamfunction 62 | ocean/visualization 63 | 64 | .. toctree:: 65 | :caption: Sea-ice Tools 66 | :maxdepth: 2 67 | 68 | seaice/mask 69 | seaice/mesh 70 | seaice/partition 71 | seaice/regions 72 | seaice/regrid 73 | 74 | .. toctree:: 75 | :caption: Developer's Guide 76 | :maxdepth: 2 77 | 78 | making_changes 79 | testing_changes 80 | building_docs 81 | 82 | api 83 | 84 | Indices and tables 85 | ================== 86 | 87 | * :ref:`genindex` 88 | 89 | .. toctree:: 90 | :caption: Authors 91 | :maxdepth: 1 92 | 93 | authors 94 | -------------------------------------------------------------------------------- /conda_package/docs/interpolation.rst: -------------------------------------------------------------------------------- 1 | .. _mesh_interpolation: 2 | 3 | .. |---| unicode:: U+2014 .. em dash, trimming surrounding whitespace 4 | :trim: 5 | 6 | ************* 7 | Interpolation 8 | ************* 9 | 10 | Previously, various tools in this package used ``scipy`` for interpolation. 11 | However, the interpolation routines in ``scipy`` are not well suited to 12 | interpolation from regular grids to MPAS meshes---they are slow and very memory 13 | intensive, particularly for large meshes. 14 | 15 | For bilinear interpolation from a tensor lon/lat grid to an MPAS mesh, it will 16 | be faster to use the function 17 | :py:func:`mpas_tools.mesh.interpolation.interp_bilin()` 18 | Here is an example where we define cell width for an EC mesh (see 19 | :ref:`ec_mesh`), read in longitude and latitude from an MPAS mesh, and 20 | interpolate the cell widths to cell centers on the MPAS mesh. 21 | 22 | .. code-block:: python 23 | 24 | import numpy as np 25 | import netCDF4 as nc4 26 | from mpas_tools.mesh.interpolation import interp_bilin 27 | 28 | dlon = 1. 29 | dlat = dlon 30 | earth_radius = constants['SHR_CONST_REARTH'] 31 | nlon = int(360./dlon) + 1 32 | nlat = int(180./dlat) + 1 33 | lon = np.linspace(-180., 180., nlon) 34 | lat = np.linspace(-90., 90., nlat) 35 | 36 | cellWidth = mdt.EC_CellWidthVsLat(lat) 37 | 38 | # broadcast cellWidth to 2D 39 | _, cellWidth = np.meshgrid(lon, cellWidthVsLat) 40 | 41 | ds = nc4.Dataset('base_mesh.nc', 'r+') 42 | lonCell = ds.variables['lonCell'][:] 43 | latCell = ds.variables['latCell'][:] 44 | 45 | lonCell = np.mod(np.rad2deg(lonCell) + 180., 360.) - 180. 46 | latCell = np.rad2deg(latCell) 47 | 48 | cellWidthOnMpas = interp_bilin(lon, lat, cellWidth, lonCell, latCell) 49 | -------------------------------------------------------------------------------- /conda_package/docs/io.rst: -------------------------------------------------------------------------------- 1 | .. _io: 2 | 3 | ********* 4 | I/O Tools 5 | ********* 6 | 7 | The :py:mod:`mpas_tools.io` module provides utilities for reading and writing 8 | NetCDF files, especially for compatibility with MPAS mesh and data conventions. 9 | 10 | write_netcdf 11 | ============ 12 | 13 | The :py:func:`mpas_tools.io.write_netcdf()` function writes an 14 | ``xarray.Dataset`` to a NetCDF file, ensuring MPAS compatibility (e.g., 15 | converting int64 to int32, handling fill values, and updating the history 16 | attribute). It also supports writing in various NetCDF formats, including 17 | conversion to ``NETCDF3_64BIT_DATA`` using ``ncks`` if needed. 18 | 19 | Example usage: 20 | 21 | .. code-block:: python 22 | 23 | import xarray as xr 24 | from mpas_tools.io import write_netcdf 25 | 26 | # Create a simple dataset 27 | ds = xr.Dataset({'foo': (('x',), [1, 2, 3])}) 28 | write_netcdf(ds, 'output.nc') 29 | -------------------------------------------------------------------------------- /conda_package/docs/ocean/depth.rst: -------------------------------------------------------------------------------- 1 | .. _ocean_depth: 2 | 3 | Adding a Depth Coordinate 4 | ========================= 5 | 6 | Adding a 1D depth coordinate 7 | ---------------------------- 8 | 9 | The function :py:func:`mpas_tools.ocean.depth.add_depth()` can be used to add 10 | a 1D ``depth`` coordinate that is appropriate for runs with a z-star MPAS-Ocean 11 | mesh. The coordinate is only approximately correct but is useful for 12 | visualization. 13 | 14 | Internally, the depth is computed with 15 | :py:func:`mpas_tools.ocean.depth.compute_depth()`, which could also be called 16 | directly if one has a suitable ``refBottomDepth`` data array indicating the 17 | reference depth of the bottom of each layer in a 1D coordinate that is 18 | independent of both time and horizontal coordinate. 19 | 20 | 21 | Adding a 3D zMid coordinate 22 | --------------------------- 23 | 24 | The function :py:func:`mpas_tools.ocean.depth.add_zmid()` can be used to add 25 | a time-independent, 3D ``zMid`` coordinate that is appropriate for runs with 26 | any MPAS-Ocean vertical coordinate that is not a significant function of time. 27 | This is appropriate for both z-star simulations and those with ice-shelf 28 | cavities, which have a more complex vertical coordinate. The coordinate is only 29 | approximately correct because MPAS-Ocean coordinates vary at least slightly 30 | in time (with the undulation of the sea surface). The time-independent ``zMid`` 31 | is appropriate for visualization an analysis that does not need to account for 32 | this time variability. 33 | 34 | Internally, the ``zMid`` is computed with 35 | :py:func:`mpas_tools.ocean.depth.compute_zmid()`, which could also be called 36 | directly if one has a suitable ``bottomDepth``, ``maxLevelCell``, 37 | and (reference) ``layerThickness`` data arrays. 38 | 39 | 40 | Writing a time-dependent, 3D zMid variable 41 | ------------------------------------------ 42 | 43 | The function :py:func:`mpas_tools.ocean.depth.write_time_varying_zmid()` can be 44 | used to write out a time-dependent, 3D ``zMid`` variable to its own file. 45 | This is the "true" MPAS-Ocean vertical coordinate, in contrast to the 1D and 46 | 3D time-independent coordinates mentioned above. However, it requires a 47 | significant amount of disk space so may not be desirable in many contexts. 48 | 49 | Internally, the ``zMid`` is computed with 50 | :py:func:`mpas_tools.ocean.depth.compute_zmid()` using the time-dependent 51 | ``layerThickness`` variable, where ```` is a prefix such as 52 | ``'timeMonthly_avg_'`` or an empty string (``''``) for no prefix. 53 | -------------------------------------------------------------------------------- /conda_package/docs/ocean/mesh_creation.rst: -------------------------------------------------------------------------------- 1 | .. _ocean_mesh_creation: 2 | 3 | Ocean Mesh Creation 4 | =================== 5 | 6 | The :py:mod:`mpas_tools.ocean.build_mesh` module is used create 7 | ocean-specific MPAS meshes using the 8 | :py:mod:`mpas_tools.mesh.creation.build_mesh` module. 9 | 10 | Spherical meshes are constructed with the function 11 | :py:func:`mpas_tools.ocean.build_mesh.build_spherical_mesh()`. The basic 12 | arguments are the same as those to 13 | :py:func:`mpas_tools.mesh.creation.build_mesh.build_spherical_mesh()`. 14 | 15 | Similarly, planar meshes can be constructed with the function 16 | :py:func:`mpas_tools.ocean.build_mesh.build_planar_mesh()`, which has the 17 | same basic arguments as 18 | :py:func:`mpas_tools.mesh.creation.build_mesh.build_planar_mesh()`. 19 | 20 | Each of these functions has additional, optional arguments that allow users to: 21 | 22 | * specify a directory for extracting VTK geometry for viewing in 23 | `ParaVeiw `_. 24 | The :py:func:`mpas_tools.viz.paraview_extractor.extract_vtk` function is 25 | used to produce a VTK file in this directory, named ``base_mesh_vtk`` 26 | by default. 27 | 28 | * Specify whether to preserve a region of the mesh above sea level as a 29 | floodplain, and the elevation up to which this regions should remain part 30 | of the mesh. This feature is used in coastal simulations that support 31 | wetting and drying. A field, ``cellSeedMask``, is added to the mesh file 32 | that can later be used preserve the floodplain. 33 | See :py:func:`mpas_tools.ocean.inject_preserve_floodplain.inject_preserve_floodplain`. 34 | 35 | 36 | * Whether to add a default bathymetry data set to the mesh. A field, 37 | ``bottomDepthObserved``, is added to the mesh file with bathymetry data 38 | from one of two topography files: ``earth_relief_15s.nc`` or ``topo.msh``. 39 | If bathymetry should be added to the mesh, a local link with one of these 40 | file names must exist. 41 | See :py:func:`mpas_tools.ocean.inject_bathymetry.inject_bathymetry`. 42 | -------------------------------------------------------------------------------- /conda_package/docs/ocean/streamfunction.rst: -------------------------------------------------------------------------------- 1 | .. _ocean_streamfunction: 2 | 3 | Computing streamfunctions 4 | ========================= 5 | 6 | Computing the barotropic streamfunction 7 | --------------------------------------- 8 | 9 | The function :py:func:`mpas_tools.ocean.compute_barotropic_streamfunction()` 10 | computes the barotproic streamfunction at vertices on the MPAS-Ocean grid. 11 | The function takes a dataset containing an MPAS-Ocean mesh and another with 12 | ``normalVelocity`` and ``layerThickness`` variables (possibly with a 13 | ``timeMonthly_avg_`` prefix). The streamfunction is computed only over the 14 | range of (positive-down) depths provided and at the given time index. 15 | -------------------------------------------------------------------------------- /conda_package/docs/seaice/mask.rst: -------------------------------------------------------------------------------- 1 | .. _seaice_mask: 2 | 3 | Mask 4 | ==== 5 | 6 | The :py:mod:`mpas_tools.seaice.mask` module contains a function for 7 | manipulating sea-ice region masks. 8 | 9 | .. _seaice_mask_extend_seaice_mask: 10 | 11 | Extending a Mask 12 | ---------------- 13 | 14 | The function :py:func:`mpas_tools.seaice.mask.extend_seaice_mask()` is used to 15 | extend a sea-ice "presence" mask that covers the area where sea-ice is present 16 | by a given distance. This is useful as part of creating a sea-ice 17 | :ref:`seaice_partition`. 18 | -------------------------------------------------------------------------------- /conda_package/docs/seaice/mesh.rst: -------------------------------------------------------------------------------- 1 | .. _seaice_mesh: 2 | 3 | Mesh 4 | ==== 5 | 6 | The :py:mod:`mpas_tools.seaice.mesh` module contains several functions for 7 | creating scrip files for sea-ice meshes and regular grids. 8 | 9 | .. _seaice_mesh_mpas_scrip: 10 | 11 | MPAS-Seaice SCRIP files 12 | ----------------------- 13 | 14 | The functions :py:func:`mpas_tools.seaice.mesh.make_mpas_scripfile_on_cells()` 15 | and :py:func:`mpas_tools.seaice.mesh.make_mpas_scripfile_on_vertices()` are for 16 | creating scrip files for fields on cells and vertices, respectively. 17 | 18 | These are both created using a lower-level function 19 | :py:func:`mpas_tools.seaice.mesh.write_scrip_file()`. 20 | 21 | 22 | .. _seaice_mesh_2d_scrip: 23 | 24 | SCRIP files for 2D grids 25 | ------------------------ 26 | 27 | The function :py:func:`mpas_tools.seaice.mesh.write_2D_scripfile()` is for 28 | creating scrip files for a regular, 2D latitude/longitude grid. 29 | -------------------------------------------------------------------------------- /conda_package/docs/seaice/regions.rst: -------------------------------------------------------------------------------- 1 | .. _seaice_regions: 2 | 3 | Region masks 4 | ============ 5 | 6 | The :py:mod:`mpas_tools.seaice.regions` module contains a function for 7 | creating masks to help with graph partitioning. 8 | 9 | .. _seaice_regions_make_regions_file: 10 | 11 | Make a region mask for partitioning 12 | ----------------------------------- 13 | 14 | The function :py:func:`mpas_tools.seaice.regions.make_regions_file()` is used 15 | to create a ``region`` field with different integer values for different 16 | regions that are used as part of creating a sea-ice :ref:`seaice_partition`. 17 | -------------------------------------------------------------------------------- /conda_package/docs/seaice/regrid.rst: -------------------------------------------------------------------------------- 1 | .. _seaice_regrid: 2 | 3 | Regrid 4 | ====== 5 | 6 | The :py:mod:`mpas_tools.seaice.regrid` module contains a function for 7 | regridding between MPAS-Seaice meshes. 8 | 9 | .. _seaice_regrid_regrid_to_other_mesh: 10 | 11 | Regridding between MPAS-Seaice meshes 12 | ------------------------------------- 13 | 14 | The function :py:func:`mpas_tools.seaice.regrid.regrid_to_other_mesh()` is used 15 | to regrid between MPAS-Seaice meshes, used as part of preparing for sea-ice 16 | :ref:`seaice_partition`. 17 | -------------------------------------------------------------------------------- /conda_package/docs/shared/version-switcher.js: -------------------------------------------------------------------------------- 1 | (async function () { 2 | const container = document.getElementById("version-switcher"); 3 | if (!container) return; 4 | 5 | const metaVersion = document.querySelector('meta[name="doc-version"]'); 6 | const currentVersion = metaVersion ? metaVersion.content : "unknown"; 7 | console.log("Detected current version:", currentVersion); 8 | 9 | async function fetchVersions() { 10 | try { 11 | const scriptUrl = document.currentScript.src; 12 | const basePath = scriptUrl.substring(0, scriptUrl.lastIndexOf('/') + 1); 13 | const versionsUrl = basePath + "versions.json"; 14 | 15 | const res = await fetch(versionsUrl); 16 | if (!res.ok) throw new Error(`Failed to load ${versionsUrl}`); 17 | return await res.json(); 18 | } catch (err) { 19 | console.error("Could not load versions.json:", err); 20 | return []; 21 | } 22 | } 23 | 24 | const versions = await fetchVersions(); 25 | if (!versions.length) return; 26 | 27 | const select = document.createElement("select"); 28 | select.style.marginLeft = "1em"; 29 | select.onchange = () => { 30 | window.location.href = select.value; 31 | }; 32 | 33 | versions.forEach(({ version, url }) => { 34 | const option = document.createElement("option"); 35 | option.value = url; 36 | option.textContent = version; 37 | if (version === currentVersion) { 38 | option.selected = true; 39 | } 40 | select.appendChild(option); 41 | }); 42 | 43 | const label = document.createElement("label"); 44 | label.textContent = "Version: "; 45 | label.style.color = "white"; 46 | label.appendChild(select); 47 | container.appendChild(label); 48 | })(); 49 | 50 | -------------------------------------------------------------------------------- /conda_package/docs/testing_changes.rst: -------------------------------------------------------------------------------- 1 | .. _dev_testing_changes: 2 | 3 | ***************************** 4 | Testing Changes to mpas_tools 5 | ***************************** 6 | 7 | Here, we describe the workflow for creating a development conda environment 8 | that points to ``mpas_tools`` in a branch from a local clone of the repo. 9 | This approach works both for calling functions from the package within a python 10 | script or another python package and for calling the "entry points" 11 | (command-line tools; see :ref:`dev_making_changes`). 12 | 13 | Basic instructions on how to install `Miniconda `_ 14 | are beyond the scope of this documentation. Make sure the conda-forge channel 15 | is added and that channel priority is "strict", meaning packages will 16 | definitely come from conda-forge if they are available there. 17 | 18 | .. code-block:: bash 19 | 20 | conda config --add channels conda-forge 21 | conda config --set channel_priority strict 22 | 23 | To make a conda environment and install the current `mpas_tools` in a way that 24 | it will be used out of the repo directly (i.e. it will notice changes as you 25 | make them in your branch), run: 26 | 27 | .. code-block:: bash 28 | 29 | cd conda_package 30 | conda env create -y -n mpas_tools_dev --file dev-spec.txt 31 | conda activate mpas_tools_dev 32 | python -m pip install --no-deps --no-build-isolation -e . 33 | 34 | You should now find that ``mpas_tools`` can be imported in python codes and the 35 | various scripts and entry points are available in the path. 36 | 37 | If you have already created the ``mpas_tools_dev`` environment, it may be best 38 | to remove it (see below) and create it again. 39 | 40 | Removing the test environment 41 | ***************************** 42 | 43 | If you're done with testing, you can remove the test environment 44 | 45 | .. code-block:: 46 | 47 | conda deactivate 48 | conda remove --all -n mpas_tools_dev 49 | -------------------------------------------------------------------------------- /conda_package/docs/transects.rst: -------------------------------------------------------------------------------- 1 | .. _transects: 2 | 3 | ********* 4 | Transects 5 | ********* 6 | 7 | The :py:mod:`mpas_tools.transects` module contains functions used to define 8 | transects through MPAS meshes. These transects can be used to create masks 9 | of the cells, edges or dual-mesh cells (in some sense "vertices") that 10 | intersect the transect. They can also be used for visualization such as 11 | plotting vertical cross-sections of MPAS data along the transect. 12 | 13 | .. _subdividing_transects: 14 | 15 | Subdividing transects 16 | ===================== 17 | 18 | For both visualization and intersection detection, it is often useful to 19 | subdivide a transect into smaller segments. This is performed with the 20 | function :py:func:`mpas_tools.transects.subdivide_great_circle()` for spherical 21 | meshes and with :py:func:`mpas_tools.transects.subdivide_planar()` for planar 22 | meshes. 23 | 24 | For spherical meshes, subdivision is performed in Cartesian coordinates. Since 25 | transects are typically provided as a sequence of longitude/latitude points, 26 | it is typically necessary to convert to Cartesian coordinates using 27 | :py:func:`mpas_tools.transects.lon_lat_to_cartesian()` and then back to 28 | longitude/latitude coordinates using 29 | :py:func:`mpas_tools.transects.cartesian_to_lon_lat()`. 30 | 31 | 32 | Low-level functions 33 | =================== 34 | 35 | The module also shares some lower-level functions used elsewhere in the 36 | package. 37 | 38 | The arc length (in radians) along a transect can be found with 39 | :py:func:`mpas_tools.transects.angular_distance()`. 40 | 41 | The function :py:func:`mpas_tools.transects.intersects()` can be used to 42 | determine if 2 arcs on the sphere intersect one another and 43 | :py:func:`mpas_tools.transects.intersection()` can be used to find the 44 | intersection point of 2 intersecting arcs. 45 | -------------------------------------------------------------------------------- /conda_package/docs/vector.rst: -------------------------------------------------------------------------------- 1 | .. _vector: 2 | 3 | ***************** 4 | Vector Operations 5 | ***************** 6 | 7 | MPAS-Tools has a ``Vector`` class and an unrelated tool for performing 8 | vector reconstructions at cell centers from fields defined at edge normals. 9 | 10 | .. _vector_class: 11 | 12 | Vector Class 13 | ============ 14 | 15 | The :py:class:`mpas_tools.vector.Vector` class defines a single vector (with 16 | components that are floats) or a vector field (with components that are 17 | :py:class:`numpy.ndarray` objects). See the API documentation for the 18 | individual methods to find out more. 19 | 20 | 21 | .. _vector_reconstruct: 22 | 23 | Vector Reconstructions 24 | ====================== 25 | 26 | The command-line tool ``vector_reconstruct`` and the function 27 | :py:func:`mpas_tools.vector.reconstruct.reconstruct_variable()` are used to 28 | reconstruct Cartesian (X, Y, Z), zonal and meridional components of an MPAS 29 | vector field at cell centers, given the field on edge normals. 30 | 31 | This tool requires that the field ``coeffs_reconstruct`` has been saved to a 32 | NetCDF file. The simplest way to do this is to include the following 33 | stream in a forward run: 34 | 35 | .. code-block:: xml 36 | 37 | 42 | 43 | 44 | 45 | 46 | and run the model for one time step. 47 | 48 | Then, ``vector_reconstruct`` is called with: 49 | 50 | .. code-block:: 51 | 52 | $ vector_reconstruct --help 53 | usage: vector_reconstruct [-h] [-m MESH_FILENAME] [-w WEIGHTS_FILENAME] -i 54 | IN_FILENAME -v VARIABLES [VARIABLES ...] 55 | [--out_variables OUT_VARIABLES [OUT_VARIABLES ...]] 56 | -o OUT_FILENAME 57 | 58 | You must supply input and output files and a list of one or more variables on 59 | edge normals to reconstruct. You can optionally supply a separate file that 60 | contains the MPAS mesh if it is not part of the input file, a file with 61 | ``coeffs_reconstruct`` if it is not in the input file, and a list of variable 62 | prefixes corresponding to each variable supplied that should be prepended to 63 | the Cartesian, zonal and meridional reconstructions for that variable. 64 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/__init__.py: -------------------------------------------------------------------------------- 1 | __version_info__ = (1, 2, 0) 2 | __version__ = '.'.join(str(vi) for vi in __version_info__) 3 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/__main__.py: -------------------------------------------------------------------------------- 1 | """ 2 | MPAS mesh tools 3 | """ 4 | 5 | from __future__ import absolute_import, division, print_function, \ 6 | unicode_literals 7 | 8 | import mpas_tools 9 | 10 | import argparse 11 | 12 | 13 | def main(): 14 | """ 15 | Entry point for the main script ``mpas_tools`` 16 | """ 17 | 18 | parser = argparse.ArgumentParser( 19 | description=__doc__, formatter_class=argparse.RawTextHelpFormatter) 20 | parser.add_argument('-v', '--version', 21 | action='version', 22 | version='mpas_tools {}'.format( 23 | mpas_tools.__version__), 24 | help="Show version number and exit") 25 | 26 | args = parser.parse_args() 27 | 28 | 29 | if __name__ == "__main__": 30 | main() 31 | 32 | # vim: foldmethod=marker ai ts=4 sts=4 et sw=4 ft=python 33 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/cime/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/mpas_tools/cime/__init__.py -------------------------------------------------------------------------------- /conda_package/mpas_tools/cime/constants.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | constants = \ 5 | {'SHR_CONST_PI': 3.14159265358979323846, 6 | 'SHR_CONST_CDAY': 86400.0, 7 | 'SHR_CONST_SDAY': 86164.0, 8 | 'SHR_CONST_REARTH': 6.37122e6, 9 | 'SHR_CONST_G': 9.80616, 10 | 'SHR_CONST_STEBOL': 5.67e-8, 11 | 'SHR_CONST_BOLTZ': 1.38065e-23, 12 | 'SHR_CONST_AVOGAD': 6.02214e26, 13 | 'SHR_CONST_MWDAIR': 28.966, 14 | 'SHR_CONST_MWWV': 18.016, 15 | 'SHR_CONST_KARMAN': 0.4, 16 | 'SHR_CONST_PSTD': 101325.0, 17 | 'SHR_CONST_PDB': 0.0112372, 18 | 'SHR_CONST_TKTRIP': 273.16, 19 | 'SHR_CONST_TKFRZ': 273.15, 20 | 'SHR_CONST_ZSRFLYR': 3.0, 21 | 'SHR_CONST_RHOFW': 1.000e3, 22 | 'SHR_CONST_RHOSW': 1.026e3, 23 | 'SHR_CONST_RHOICE': 0.917e3, 24 | 'SHR_CONST_CPDAIR': 1.00464e3, 25 | 'SHR_CONST_CPWV': 1.810e3, 26 | 'SHR_CONST_CPFW': 4.188e3, 27 | 'SHR_CONST_CPSW': 3.996e3, 28 | 'SHR_CONST_CPICE': 2.11727e3, 29 | 'SHR_CONST_LATICE': 3.337e5, 30 | 'SHR_CONST_LATVAP': 2.501e6, 31 | 'SHR_CONST_CONDICE': 2.1, 32 | 'SHR_CONST_TF0': 6.22e-2, 33 | 'SHR_CONST_DTF_DP': -7.43e-8, 34 | 'SHR_CONST_DTF_DS': -5.63e-2, 35 | 'SHR_CONST_DTF_DPDS': -1.74e-10, 36 | 'SHR_CONST_OCN_REF_SAL': 34.7, 37 | 'SHR_CONST_ICE_REF_SAL': 4.0, 38 | 'SHR_CONST_SPVAL': 1.0e30, 39 | 'SHR_CONST_SPVAL_TOLMIN': 0.99 * 1.0e30, 40 | 'SHR_CONST_SPVAL_TOLMAX': 1.01 * 1.0e30, 41 | 'SHR_CONST_SPVAL_AERODEP': 1.e29, 42 | 'SHR_CONST_VSMOW_18O': 2005.2e-6, 43 | 'SHR_CONST_VSMOW_17O': 379.e-6, 44 | 'SHR_CONST_VSMOW_16O': 0.997628, 45 | 'SHR_CONST_VSMOW_D': 155.76e-6, 46 | 'SHR_CONST_VSMOW_T': 1.85e-6, 47 | 'SHR_CONST_VSMOW_H': 0.99984426, 48 | 'SHR_CONST_RSTD_H2ODEV': 1.0} 49 | 50 | constants['SHR_CONST_OMEGA'] = 2.0 * np.pi / constants['SHR_CONST_SDAY'] 51 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/conversion.py: -------------------------------------------------------------------------------- 1 | from mpas_tools.mesh.conversion import convert, cull, mask 2 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/landice/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/mpas_tools/landice/__init__.py -------------------------------------------------------------------------------- /conda_package/mpas_tools/landice/boundary.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from optparse import OptionParser 3 | from datetime import datetime 4 | 5 | import netCDF4 6 | 7 | 8 | def mark_domain_boundaries_dirichlet(): 9 | """ 10 | This script marks all of the boundary cells in a domain as Dirichlet 11 | velocity boundaries. 12 | """ 13 | 14 | print("== Gathering information. (Invoke with --help for more details. " 15 | "All arguments are optional)\n") 16 | parser = OptionParser() 17 | parser.description = __doc__ 18 | parser.add_option( 19 | "-f", "--file", dest="inputFile", 20 | help="name of file to be modified.", 21 | default="landice_grid.nc", metavar="FILENAME") 22 | parser.add_option( 23 | "-t", "--time", dest="time", 24 | help="time level to modify", 25 | default=0, type="int", metavar="FILENAME") 26 | for option in parser.option_list: 27 | if option.default != ("NO", "DEFAULT"): 28 | option.help += (" " if option.help else "") + "[default: %default]" 29 | options, args = parser.parse_args() 30 | 31 | print(" Input file: {}".format(options.inputFile)) 32 | print(" Time level: {}".format(options.time)) 33 | 34 | f = netCDF4.Dataset(options.inputFile, 'r+') 35 | nCells = len(f.dimensions['nCells']) 36 | mask = f.variables['dirichletVelocityMask'][options.time, :, :] 37 | cONc = f.variables['cellsOnCell'][:] 38 | nEdgesOnCell = f.variables['nEdgesOnCell'][:] 39 | 40 | mask[:] = 0 41 | for i in range(nCells): 42 | nE = nEdgesOnCell[i] 43 | if min(cONc[i, :nE]) == 0: 44 | mask[i, :] = 1 45 | f.variables['dirichletVelocityMask'][options.time, :, :] = mask[:] 46 | 47 | # Update history attribute of netCDF file 48 | thiscommand = datetime.now().strftime("%a %b %d %H:%M:%S %Y") + ": " + \ 49 | " ".join(sys.argv[:]) 50 | if hasattr(f, 'history'): 51 | newhist = '\n'.join([thiscommand, getattr(f, 'history')]) 52 | else: 53 | newhist = thiscommand 54 | setattr(f, 'history', newhist) 55 | 56 | f.close() 57 | 58 | print('\nMarking boundary cells completed.') 59 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/landice/projections.py: -------------------------------------------------------------------------------- 1 | # ======== DEFINE PROJECTIONS ============= 2 | # Create empty dictionary to store projection definitions: 3 | projections = dict() 4 | # add more as needed: 5 | 6 | # CISM's projection is as follows, with the vertical datum as EIGEN-GL04C 7 | # geoid. Datum is actually EIGEN-GL04C but that is not an option in Proj. 8 | # Therefore using EGM08 which should be within ~1m everywhere (and 10-20 9 | # cm in most places) 10 | # NOTE!!!!!! egm08_25.gtx can be downloaded from: 11 | # http://download.osgeo.org/proj/vdatum/egm08_25/egm08_25.gtx and the 12 | # path in the projection specification line should point to it! 13 | 14 | # projections['gis-bamber'] = \ 15 | # '+proj=stere +lat_ts=71.0 +lat_0=90 +lon_0=321.0 +k_0=1.0 ' 16 | # '+x_0=800000.0 +y_0=3400000.0 +ellps=WGS84 ' \ 17 | # '+geoidgrids=./egm08_25.gtx' 18 | 19 | # This version ignores the vertical datum shift, which should be a very 20 | # small error for horizontal-only positions 21 | projections['gis-bamber'] = ( 22 | '+proj=stere +lat_ts=71.0 +lat_0=90 +lon_0=321.0 +k_0=1.0 ' 23 | '+x_0=800000.0 +y_0=3400000.0 +ellps=WGS84' 24 | ) 25 | 26 | # GIMP projection: This is also polar stereographic but with different 27 | # standard parallel and using the WGS84 ellipsoid. 28 | projections['gis-gimp'] = ( 29 | '+proj=stere +lat_ts=70.0 +lat_0=90 +lon_0=315.0 +k_0=1.0 +x_0=0.0 ' 30 | '+y_0=0.0 +ellps=WGS84' 31 | ) 32 | 33 | # BEDMAP2 projection 34 | # Note: BEDMAP2 elevations use EIGEN-GL04C geoid 35 | projections['ais-bedmap2'] = ( 36 | '+proj=stere +lat_ts=-71.0 +lat_0=-90 +lon_0=0.0 +k_0=1.0 +x_0=0.0 ' 37 | '+y_0=0.0 +ellps=WGS84' 38 | ) 39 | 40 | # BEDMAP2 projection of sphere. This projection must be used to adjust MALI 41 | # mesh when performing coupled MALI-SeaLevelModel simulations. Otherwise, ice 42 | # mass won't be conserved between the MALI planar mesh and the spherical 43 | # sea-level model grid during the post-processing (output analysis) step. 44 | projections['ais-bedmap2-sphere'] = ( 45 | '+proj=stere +lat_ts=-71.0 +lat_0=-90 +lon_0=0.0 +k_0=1.0 +x_0=0.0 ' 46 | '+y_0=0.0 +ellps=sphere' 47 | ) 48 | 49 | # Standard Lat/Long 50 | projections['latlon'] = '+proj=longlat +ellps=WGS84' 51 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/mesh/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/mpas_tools/mesh/__init__.py -------------------------------------------------------------------------------- /conda_package/mpas_tools/mesh/creation/__init__.py: -------------------------------------------------------------------------------- 1 | from mpas_tools.mesh.creation.build_mesh import build_spherical_mesh, \ 2 | build_planar_mesh 3 | from mpas_tools.mesh.creation.triangle_to_netcdf import triangle_to_netcdf 4 | from mpas_tools.mesh.creation.jigsaw_to_netcdf import jigsaw_to_netcdf 5 | from mpas_tools.mesh.creation.mpas_to_triangle import mpas_to_triangle 6 | from mpas_tools.mesh.creation.open_msh import readmsh 7 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/mesh/creation/open_msh.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | 4 | Utility functions to read and manipulate JIGSAW meshes. 5 | 6 | Phillip J. Wolfram 7 | 04/06/2017 8 | """ 9 | from __future__ import absolute_import, division, print_function, \ 10 | unicode_literals 11 | 12 | import numpy as np 13 | 14 | 15 | def readmsh(fname): 16 | """ 17 | Reads JIGSAW msh structure and produces a dictionary with values. 18 | 19 | Phillip J. Wolfram 20 | 09/22/2017 21 | """ 22 | 23 | dataset = {} 24 | datavals = {} 25 | datavals['HEADER'] = ';' 26 | datavals['ARRAY'] = None 27 | with open(fname) as f: 28 | line = f.readline() 29 | while line: 30 | if line[0] == '#': 31 | datavals['HEADER'] += line[1:] + ';' 32 | line = f.readline() 33 | continue 34 | if '=' in line: 35 | datavals, dataset = _store_datavals(datavals, dataset) 36 | if 'COORD' in line: 37 | name = 'COORD' + line.split('=')[1][0] 38 | datavals[name] = line.split(';')[-1] 39 | else: 40 | vals = line.split('=') 41 | value = vals[1] if ';' in vals[1] else int(vals[1]) 42 | datavals[vals[0]] = value 43 | line = f.readline() 44 | continue 45 | 46 | # just numbers 47 | arrayvals = np.asarray(line.split(';'), dtype='f8') 48 | if datavals['ARRAY'] is None: 49 | datavals['ARRAY'] = [arrayvals] 50 | else: 51 | datavals['ARRAY'].append(arrayvals) 52 | line = f.readline() 53 | continue 54 | datavals, dataset = _store_datavals(datavals, dataset) 55 | 56 | return dataset 57 | 58 | 59 | def _store_datavals(datavals, dataset): # {{{ 60 | 61 | if datavals['ARRAY'] is not None: 62 | # remove empty data 63 | if np.all(datavals['ARRAY'] == np.array(None, dtype='object')): 64 | datavals.pop('ARRAY') 65 | for key in [aval for aval in datavals.keys() 66 | if aval in ['HEADER', 'MSHID', 'NDIMS']]: 67 | if key in dataset: 68 | dataset[key] += datavals[key] 69 | else: 70 | dataset[key] = datavals[key] 71 | datavals.pop(key) 72 | entryname = [aval for aval in datavals.keys() if aval not in [ 73 | 'ARRAY']] 74 | 75 | if 'TRI' in entryname[0]: 76 | dtype = 'i' 77 | else: 78 | dtype = 'f8' 79 | datavals['ARRAY'] = np.asarray(datavals['ARRAY'], dtype=dtype) 80 | 81 | # decided to throw away "index" from msh because it isn't truly a 82 | # real number 83 | dataset[entryname[0]] = datavals['ARRAY'] 84 | datavals = {} 85 | datavals['ARRAY'] = None 86 | 87 | return datavals, dataset # }}} 88 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/mesh/creation/util.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def circumcenter(on_sphere, x1, y1, z1, x2, y2, z2, x3, y3, z3): 5 | """ 6 | Compute the circumcenter of the triangle (possibly on a sphere) 7 | with the three given vertices in Cartesian coordinates. 8 | 9 | Parameters 10 | ---------- 11 | on_sphere : bool 12 | If True, the circumcenter is computed on a sphere. 13 | If False, the circumcenter is computed in Cartesian coordinates. 14 | 15 | x1, y1, z1 : float or numpy.ndarray 16 | Cartesian coordinates of the first vertex 17 | 18 | x2, y2, z2 : float or numpy.ndarray 19 | Cartesian coordinates of the second vertex 20 | 21 | x3, y3, z3 : float or numpy.ndarray 22 | Cartesian coordinates of the third vertex 23 | 24 | Returns 25 | ------- 26 | xv, yv, zv : float or numpy.ndarray 27 | The circumcenter(s) of the triangle(s) 28 | """ 29 | x1 = np.asarray(x1) 30 | y1 = np.asarray(y1) 31 | z1 = np.asarray(z1) 32 | x2 = np.asarray(x2) 33 | y2 = np.asarray(y2) 34 | z2 = np.asarray(z2) 35 | x3 = np.asarray(x3) 36 | y3 = np.asarray(y3) 37 | z3 = np.asarray(z3) 38 | 39 | if on_sphere: 40 | a = (x2 - x3) ** 2 + (y2 - y3) ** 2 + (z2 - z3) ** 2 41 | b = (x3 - x1) ** 2 + (y3 - y1) ** 2 + (z3 - z1) ** 2 42 | c = (x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2 43 | 44 | pbc = a * (-a + b + c) 45 | apc = b * (a - b + c) 46 | abp = c * (a + b - c) 47 | 48 | denom = pbc + apc + abp 49 | xv = (pbc * x1 + apc * x2 + abp * x3) / denom 50 | yv = (pbc * y1 + apc * y2 + abp * y3) / denom 51 | zv = (pbc * z1 + apc * z2 + abp * z3) / denom 52 | else: 53 | d = 2 * (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)) 54 | 55 | xv = ( 56 | (x1**2 + y1**2) * (y2 - y3) 57 | + (x2**2 + y2**2) * (y3 - y1) 58 | + (x3**2 + y3**2) * (y1 - y2) 59 | ) / d 60 | yv = ( 61 | (x1**2 + y1**2) * (x3 - x2) 62 | + (x2**2 + y2**2) * (x1 - x3) 63 | + (x3**2 + y3**2) * (x2 - x1) 64 | ) / d 65 | zv = np.zeros_like(xv) 66 | 67 | return xv, yv, zv 68 | 69 | 70 | def lonlat2xyz(lon, lat, R=6378206.4): 71 | """ 72 | Convert from longitude and latitude to Cartesian coordinates 73 | 74 | Parameters 75 | ---------- 76 | lon : float or numpy.ndarray 77 | longitude 78 | lat : float or numpy.ndarray 79 | latitude 80 | R : float, optional 81 | Earth radius in meters 82 | 83 | Returns 84 | ------- 85 | x, y, z: float or numpy.array 86 | Cartesian coordinates 87 | """ 88 | 89 | lon = np.deg2rad(lon) 90 | lat = np.deg2rad(lat) 91 | x = R * np.multiply(np.cos(lon), np.cos(lat)) 92 | y = R * np.multiply(np.sin(lon), np.cos(lat)) 93 | z = R * np.sin(lat) 94 | 95 | return x, y, z 96 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/mesh/interpolation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | def interp_bilin(x, y, field, xCell, yCell): 5 | """ 6 | Perform bilinear interpolation of ``field`` on a tensor grid to cell centers 7 | on an MPAS mesh. ``xCell`` and ``yCell`` must be bounded by ``x`` and ``y``, 8 | respectively. 9 | 10 | If x and y coordinates are longitude and latitude, respectively, it is 11 | recommended that they be passed in degrees to avoid round-off problems at 12 | the north and south poles and at the date line. 13 | 14 | Parameters 15 | ---------- 16 | x : ndarray 17 | x coordinate of the input field (length n) 18 | 19 | y : ndarray 20 | y coordinate fo the input field (length m) 21 | 22 | field : ndarray 23 | a field of size m x n 24 | 25 | xCell : ndarray 26 | x coordinate of MPAS cell centers 27 | 28 | yCell : ndarray 29 | y coordinate of MPAS cell centers 30 | 31 | Returns 32 | ------- 33 | mpasField : ndarray 34 | ``field`` interpoyed to MPAS cell centers 35 | """ 36 | 37 | assert np.all(xCell >= x[0]) 38 | assert np.all(xCell <= x[-1]) 39 | assert np.all(yCell >= y[0]) 40 | assert np.all(yCell <= y[-1]) 41 | 42 | # find float indices into the x and y arrays of cells on the MPAS mesh 43 | xFrac = np.interp(xCell, x, np.arange(len(x))) 44 | yFrac = np.interp(yCell, y, np.arange(len(y))) 45 | 46 | # xIndices/yIndices are the integer indices of the lower bound for bilinear 47 | # interpoyion; xFrac/yFrac are the fraction of the way ot the next index 48 | xIndices = np.array(xFrac, dtype=int) 49 | xFrac -= xIndices 50 | yIndices = np.array(yFrac, dtype=int) 51 | yFrac -= yIndices 52 | 53 | # If points are exactly at the upper index, this is going to give us a bit 54 | # of trouble so we'll move them down one index and adjust the fraction 55 | # accordingly 56 | mask = xIndices == len(x) - 1 57 | xIndices[mask] -= 1 58 | xFrac[mask] += 1. 59 | 60 | mask = yIndices == len(y) - 1 61 | yIndices[mask] -= 1 62 | yFrac[mask] += 1. 63 | 64 | mpasField = \ 65 | (1. - xFrac) * (1. - yFrac) * field[yIndices, xIndices] + \ 66 | xFrac * (1. - yFrac) * field[yIndices, xIndices + 1] + \ 67 | (1. - xFrac) * yFrac * field[yIndices + 1, xIndices] + \ 68 | xFrac * yFrac * field[yIndices + 1, xIndices + 1] 69 | 70 | return mpasField 71 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/mesh/mark_horns_for_culling.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import numpy as np 3 | import netCDF4 4 | from optparse import OptionParser 5 | from datetime import datetime 6 | 7 | 8 | def main(): 9 | """ 10 | This script identifies "horns" on a mesh (cells with two or fewer 11 | neighbors), and marks them for culling. In some cores/configurations, 12 | these weakly connected cells can be dynamically inactive, and, therefore, 13 | undesirable to keep in a mesh. 14 | 15 | The method used will work on both planar and spherical meshes. 16 | It adds the new masked cell to an existing 'cullCell' field if it exists, 17 | otherwise it creates a new field. 18 | """ 19 | print("== Gathering information. (Invoke with --help for more details. " 20 | "All arguments are optional)\n") 21 | parser = OptionParser() 22 | parser.description = __doc__ 23 | parser.add_option( 24 | "-f", 25 | "--file", 26 | dest="inputFile", 27 | help="Name of file to be processed.", 28 | default="grid.nc", 29 | metavar="FILENAME") 30 | for option in parser.option_list: 31 | if option.default != ("NO", "DEFAULT"): 32 | option.help += (" " if option.help else "") + "[default: %default]" 33 | options, args = parser.parse_args() 34 | 35 | print(" File to be modified: " + options.inputFile) 36 | 37 | # Open file and get needed fields. 38 | inputFile = netCDF4.Dataset(options.inputFile, 'r+') 39 | nCells = len(inputFile.dimensions['nCells']) 40 | cellsOnCell = inputFile.variables['cellsOnCell'][:] 41 | 42 | # Add the horn cells to existing mask if it exists 43 | if 'cullCell' in inputFile.variables: 44 | cullCell = inputFile.variables['cullCell'][:] 45 | else: # otherwise make a new mask initialized empty 46 | cullCell = np.zeros((nCells,)) # local variable 47 | 48 | nHorns = 0 49 | for i in range(nCells): 50 | # NOTE: Can change this threshold, if needed for a particular use case. 51 | if (cellsOnCell[i, :] > 0).sum() <= 2: 52 | cullCell[i] = 1 53 | nHorns += 1 54 | 55 | # Write out the new field 56 | if 'cullCell' in inputFile.variables: 57 | cullCellVar = inputFile.variables['cullCell'] 58 | else: 59 | cullCellVar = inputFile.createVariable('cullCell', 'i', ('nCells',)) 60 | cullCellVar[:] = cullCell 61 | 62 | # Update history attribute of netCDF file 63 | thiscommand = datetime.now().strftime("%a %b %d %H:%M:%S %Y") + \ 64 | ": " + " ".join(sys.argv[:]) 65 | if hasattr(inputFile, 'history'): 66 | newhist = '\n'.join([thiscommand, getattr(inputFile, 'history')]) 67 | else: 68 | newhist = thiscommand 69 | setattr(inputFile, 'history', newhist) 70 | 71 | inputFile.close() 72 | 73 | print(f'\n{nHorns} "horn" locations have been marked in the field ' 74 | f'cullCell.') 75 | print("Remember to use MpasCellCuller.x to actually remove them!") 76 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/ocean/__init__.py: -------------------------------------------------------------------------------- 1 | from mpas_tools.ocean.build_mesh import ( 2 | build_spherical_mesh, 3 | build_planar_mesh, 4 | ) 5 | from mpas_tools.ocean.barotropic_streamfunction import ( 6 | compute_barotropic_streamfunction, 7 | ) 8 | from mpas_tools.ocean.inject_bathymetry import inject_bathymetry 9 | from mpas_tools.ocean.inject_meshDensity import ( 10 | inject_meshDensity_from_file, 11 | inject_spherical_meshDensity, 12 | inject_planar_meshDensity, 13 | ) 14 | from mpas_tools.ocean.inject_preserve_floodplain import ( 15 | inject_preserve_floodplain, 16 | ) 17 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/ocean/inject_preserve_floodplain.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, division, print_function, \ 2 | unicode_literals 3 | 4 | import netCDF4 as nc4 5 | import argparse 6 | 7 | 8 | def inject_preserve_floodplain(mesh_file, floodplain_elevation): 9 | 10 | nc_mesh = nc4.Dataset(mesh_file, 'r+') 11 | nc_vars = nc_mesh.variables.keys() 12 | 13 | if 'cellSeedMask' not in nc_vars: 14 | nc_mesh.createVariable('cellSeedMask', 'i', ('nCells')) 15 | nc_mesh.variables['cellSeedMask'][:] = \ 16 | nc_mesh.variables['bottomDepthObserved'][:] < floodplain_elevation 17 | 18 | nc_mesh.close() 19 | 20 | 21 | def main(): 22 | 23 | parser = argparse.ArgumentParser() 24 | parser.add_argument('mesh_file', action='store', type=str) 25 | parser.add_argument('floodplain_elevation', action='store', type=float) 26 | cl_args = parser.parse_args() 27 | 28 | inject_preserve_floodplain(cl_args.mesh_file, cl_args.floodplain_elevation) 29 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/ocean/viz/__init__.py: -------------------------------------------------------------------------------- 1 | from mpas_tools.ocean.viz.inset import add_inset # noqa: F401 2 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/ocean/viz/transect/__init__.py: -------------------------------------------------------------------------------- 1 | from mpas_tools.ocean.viz.transect.plot import ( # noqa: F401 2 | plot_feature_transects, 3 | plot_transect, 4 | ) 5 | from mpas_tools.ocean.viz.transect.vert import ( # noqa: F401 6 | compute_transect, 7 | find_transect_levels_and_weights, 8 | interp_mpas_to_transect_cells, 9 | interp_mpas_to_transect_nodes, 10 | interp_transect_grid_to_transect_nodes, 11 | ) 12 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/parallel.py: -------------------------------------------------------------------------------- 1 | import multiprocessing 2 | 3 | 4 | def create_pool(process_count=None, method='forkserver'): 5 | """ 6 | Crate a pool for creating masks with Python multiprocessing. This should 7 | be called only once at the beginning of the script performing cell culling. 8 | ``pool.terminate()`` should be called before exiting the script. 9 | 10 | Parameters 11 | ---------- 12 | process_count : int, optional 13 | The number of processors or None to use all available processors 14 | 15 | method : {'fork', 'spawn', 'forkserver'} 16 | The mutiprocessing method 17 | 18 | Returns 19 | ------- 20 | pool : multiprocessing.Pool 21 | A pool to use for python-based mask creation. 22 | """ 23 | pool = None 24 | multiprocessing.set_start_method(method) 25 | if process_count is None: 26 | process_count = multiprocessing.cpu_count() 27 | else: 28 | process_count = min(process_count, multiprocessing.cpu_count()) 29 | 30 | if process_count > 1: 31 | pool = multiprocessing.Pool(process_count) 32 | 33 | return pool 34 | 35 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/scrip/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/mpas_tools/scrip/__init__.py -------------------------------------------------------------------------------- /conda_package/mpas_tools/seaice/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/mpas_tools/seaice/__init__.py -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/Publications.bib: -------------------------------------------------------------------------------- 1 | @article{FSamsele, 2 | title = {ColorMoves: Real-time Interactive Colormap Construction for Scientific Visualization}, 3 | author = {Francesca Samsel and Sebastion Klaassen and David Rogers}, 4 | url = {http://doi.ieeecomputersociety.org/10.1109/MCG.2018.011461525}, 5 | year = {2018}, 6 | date = {2018-01-01}, 7 | abstract = {The visualization of scientific data is both a science and an art, in which many tools are used to explore, discover and communicate the information within the data. This process is increasingly difficult, as the size and complexity of data is constantly advancing. Color is a potent tool in scientific data visualization, and has been well studied. However, color’s full potential for communication and discovery remains untapped. Effective use of color requires a depth of understanding and experience employing color and color relationships, in combination with tools to translate that knowledge into scientific visualization workflows. In this paper, we present ColorMoves, an interactive tool that promotes exploration of scientific data through artist-driven color methods in a unique and transformative way. We discuss the power of contrast in scientific visualization, the design of the ColorMoves tool, and the tool’s application in several science domains.}, 8 | note = {LA-UR-17-29913}, 9 | keywords = {color, colormaps, interactive design, scientific visualization}, 10 | pubstate = {published}, 11 | tppubtype = {article} 12 | } 13 | 14 | @inproceedings{info:lanl-repo/lareport/LA-UR-17-22224, 15 | title = {Intuitive Colormaps for Environmental Visualization}, 16 | author = {Francesca Samsel and Terece Turton and Phillip Wolfram and Roxana Bujack}, 17 | editor = {Karsten Rink and Ariane Middel and Dirk Zeckzer and Roxana Bujack}, 18 | url = {http://datascience.dsscale.org/wp-content/uploads/sites/3/2017/08/IntuitiveColormapsforEnvironmentalVisualization.pdf}, 19 | doi = {10.2312/envirvis.20171105}, 20 | isbn = {978-3-03868-040-6}, 21 | year = {2017}, 22 | date = {2017-03-16}, 23 | booktitle = {Workshop on Visualisation in Environmental Sciences (EnvirVis)}, 24 | publisher = {The Eurographics Association}, 25 | abstract = {Visualizations benefit from the use of intuitive colors, enabling an observer to make use of more automatic, subconscious channels. In this paper, we apply the concept of intuitive color to the generation of thematic colormaps for the environmental sciences. In particular, we provide custom sets of colormaps for water, atmosphere, land, and vegetation. These have been integrated into the online tool: ColorMoves: The Environment to enable the environmental scientist to tailor them precisely to the data and tasks in a simple drag-and-drop workflow.}, 26 | howpublished = {EnvirVis ; 2017-06-12 - 2017-06-13 ; Barcelona, Spain}, 27 | note = {LA-UR-17-22224}, 28 | keywords = {colormaps, environmental sciences}, 29 | pubstate = {published}, 30 | tppubtype = {inproceedings} 31 | } 32 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/mpas_tools/viz/SciVisColorColormaps/__init__.py -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/blue-1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/blue-3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/blue-6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/blue-8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/brown-2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/brown-5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/brown-8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/green-1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/green-4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/green-7.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/green-8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/orange-5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/orange-6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/purple-7.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/purple-8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/red-1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/red-3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/red-4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/yellow-1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/SciVisColorColormaps/yellow-7.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/__init__.py: -------------------------------------------------------------------------------- 1 | from mpas_tools.viz.mesh_to_triangles import mesh_to_triangles 2 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/colormaps.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as ET 2 | from importlib.resources import files as imp_res_files 3 | from matplotlib.colors import LinearSegmentedColormap 4 | import matplotlib.pyplot as plt 5 | from matplotlib import colormaps 6 | 7 | 8 | def register_sci_viz_colormaps(): 9 | """Register all SciVisColor colormaps with matplotlib""" 10 | 11 | for mapName in ['3wave-yellow-grey-blue', '3Wbgy5', 12 | '4wave-grey-red-green-mgreen', '5wave-yellow-brown-blue', 13 | 'blue-1', 'blue-3', 'blue-6', 'blue-8', 'blue-orange-div', 14 | 'brown-2', 'brown-5', 'brown-8', 'green-1', 'green-4', 15 | 'green-7', 'green-8', 'orange-5', 'orange-6', 16 | 'orange-green-blue-gray', 'purple-7', 'purple-8', 'red-1', 17 | 'red-3', 'red-4', 'yellow-1', 'yellow-7']: 18 | xmlFile = str(imp_res_files('mpas_tools.viz.SciVisColorColormaps') / 19 | f'{mapName}.xml') 20 | _read_xml_colormap(xmlFile, mapName) 21 | 22 | 23 | def _read_xml_colormap(xmlFile, mapName): 24 | """Read in an XML colormap""" 25 | 26 | xml = ET.parse(xmlFile) 27 | 28 | root = xml.getroot() 29 | colormap = root.findall('ColorMap') 30 | if len(colormap) > 0: 31 | colormap = colormap[0] 32 | colorDict = {'red': [], 'green': [], 'blue': []} 33 | for point in colormap.findall('Point'): 34 | x = float(point.get('x')) 35 | color = [float(point.get('r')), float(point.get('g')), 36 | float(point.get('b'))] 37 | colorDict['red'].append((x, color[0], color[0])) 38 | colorDict['green'].append((x, color[1], color[1])) 39 | colorDict['blue'].append((x, color[2], color[2])) 40 | cmap = LinearSegmentedColormap(mapName, colorDict, 256) 41 | 42 | _register_colormap_and_reverse(mapName, cmap) 43 | 44 | 45 | def _register_colormap_and_reverse(mapName, cmap): 46 | if mapName not in plt.colormaps(): 47 | colormaps.register(cmap=cmap, name=mapName) 48 | colormaps.register(cmap=cmap.reversed(), name='{}_r'.format(mapName)) 49 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/mpas_to_xdmf/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/mpas_tools/viz/mpas_to_xdmf/__init__.py -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/mpas_to_xdmf/mesh.py: -------------------------------------------------------------------------------- 1 | _mesh_vars = [ 2 | 'areaCell', 3 | 'cellsOnCell', 4 | 'edgesOnCell', 5 | 'indexToCellID', 6 | 'latCell', 7 | 'lonCell', 8 | 'nEdgesOnCell', 9 | 'verticesOnCell', 10 | 'xCell', 11 | 'yCell', 12 | 'zCell', 13 | 'angleEdge', 14 | 'cellsOnEdge', 15 | 'dcEdge', 16 | 'dvEdge', 17 | 'edgesOnEdge', 18 | 'indexToEdgeID', 19 | 'latEdge', 20 | 'lonEdge', 21 | 'nEdgesOnCell', 22 | 'nEdgesOnEdge', 23 | 'verticesOnEdge', 24 | 'xEdge', 25 | 'yEdge', 26 | 'zEdge', 27 | 'areaTriangle', 28 | 'cellsOnVertex', 29 | 'edgesOnVertex', 30 | 'indexToVertexID', 31 | 'kiteAreasOnVertex', 32 | 'latVertex', 33 | 'lonVertex', 34 | 'xVertex', 35 | 'yVertex', 36 | 'zVertex', 37 | 'weightsOnEdge', 38 | ] 39 | 40 | 41 | def _get_ds_mesh(ds): 42 | """ 43 | Extract the mesh variables from an xarray Dataset. 44 | 45 | Parameters 46 | ---------- 47 | ds : xarray.Dataset 48 | The xarray Dataset containing the mesh data. 49 | 50 | Returns 51 | ------- 52 | xarray.Dataset 53 | A new Dataset containing only the specified mesh variables. 54 | """ 55 | ds_mesh = ds[_mesh_vars] 56 | return ds_mesh 57 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/mpas_to_xdmf/templates/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/mpas_tools/viz/mpas_to_xdmf/templates/__init__.py -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/mpas_to_xdmf/templates/xdmf_template.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% if times|length > 0 %} 6 | {% set t_index = 0 %} 7 | {% for t_val in times %} 8 | 9 | 28 | {% set t_index = t_index + 1 %} 29 | {% endfor %} 30 | {% else %} 31 | 32 | 33 | {{ h5_basename }}:/Cells 34 | 35 | 36 | {{ h5_basename }}:/Points 37 | 38 | {% for var in variables %} 39 | {% if not var.has_time %} 40 | 41 | {{ h5_basename }}:/{{ var.name }} 42 | 43 | {% endif %} 44 | {% endfor %} 45 | 46 | {% endif %} 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/mpas_to_xdmf/time.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Optional 3 | 4 | import numpy as np 5 | import xarray as xr 6 | 7 | 8 | def _set_time(ds: xr.Dataset, xtime_var: Optional[str]): 9 | """ 10 | Set the time variable in the dataset to be a DataArray of seconds since 11 | the first entry. 12 | 13 | Parameters 14 | ---------- 15 | ds : xr.Dataset 16 | The dataset containing the time variable. 17 | xtime_var : str 18 | The name of the time variable in the dataset. 19 | """ 20 | if 'Time' in ds.dims: 21 | if xtime_var is not None: 22 | if xtime_var not in ds.data_vars: 23 | raise ValueError( 24 | f"xtime variable '{xtime_var}' not found in dataset." 25 | ) 26 | ds['Time'] = _xtime_to_seconds(ds[xtime_var]) 27 | else: 28 | ds['Time'] = xr.DataArray(np.arange(ds.sizes['Time']), dims='Time') 29 | 30 | 31 | def _xtime_to_seconds(xtime: xr.DataArray) -> xr.DataArray: 32 | """ 33 | Convert an xarray DataArray of xtime strings to seconds since the first 34 | entry. 35 | 36 | Parameters 37 | ---------- 38 | xtime : xr.DataArray 39 | An array of strings representing time in the format 40 | 'YYYY-MM-DD_HH:MM:SS.sss'. 41 | 42 | Returns 43 | ------- 44 | xr.DataArray 45 | An array of seconds since the first entry in `xtime`. 46 | """ 47 | # Convert xtime strings to datetime objects using datetime.strptime 48 | timestamps = [ 49 | datetime.strptime(time_str, '%Y-%m-%d_%H:%M:%S.%f') 50 | for time_str in xtime.values.astype(str) 51 | ] 52 | # Calculate seconds since the first timestamp 53 | seconds_since_start = [ 54 | (ts - timestamps[0]).total_seconds() for ts in timestamps 55 | ] 56 | # Return as a DataArray 57 | return xr.DataArray( 58 | seconds_since_start, dims=xtime.dims, coords=xtime.coords 59 | ) 60 | -------------------------------------------------------------------------------- /conda_package/mpas_tools/viz/transect/__init__.py: -------------------------------------------------------------------------------- 1 | from mpas_tools.viz.transect.horiz import ( # noqa: F401 2 | find_planar_transect_cells_and_weights, 3 | find_spherical_transect_cells_and_weights, 4 | interp_mpas_horiz_to_transect_nodes, 5 | make_triangle_tree, 6 | mesh_to_triangles, 7 | ) 8 | -------------------------------------------------------------------------------- /conda_package/recipe/build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | set -e 5 | 6 | cd conda_package 7 | ${PYTHON} -m pip install . --no-deps --no-build-isolation -vv 8 | 9 | # build and install ocean topography smoothing tool 10 | cd ${SRC_DIR}/ocean/smooth_topo 11 | mkdir build 12 | cd build 13 | cmake \ 14 | -D CMAKE_INSTALL_PREFIX=${PREFIX} \ 15 | -D CMAKE_BUILD_TYPE=Release \ 16 | .. 17 | cmake --build . 18 | cmake --install . 19 | 20 | # build and install sea ice partitioning tool 21 | cd ${SRC_DIR}/mesh_tools/seaice_grid_tools 22 | mkdir build 23 | cd build 24 | cmake \ 25 | -D CMAKE_INSTALL_PREFIX=${PREFIX} \ 26 | -D CMAKE_BUILD_TYPE=Release \ 27 | .. 28 | cmake --build . 29 | cmake --install . 30 | 31 | # build and install legacy mask creator 32 | cd ${SRC_DIR}/mesh_tools/mesh_conversion_tools 33 | mkdir build 34 | cd build 35 | cmake \ 36 | -D CMAKE_INSTALL_PREFIX=${PREFIX} \ 37 | -D CMAKE_BUILD_TYPE=Release \ 38 | .. 39 | cmake --build . 40 | cp MpasMaskCreator.x ${PREFIX}/bin 41 | 42 | # build and install mesh conversion tools 43 | cd ${SRC_DIR}/mesh_tools/mesh_conversion_tools_netcdf_c 44 | mkdir build 45 | cd build 46 | cmake \ 47 | -D CMAKE_INSTALL_PREFIX=${PREFIX} \ 48 | -D CMAKE_BUILD_TYPE=Release \ 49 | .. 50 | cmake --build . 51 | cmake --install . 52 | -------------------------------------------------------------------------------- /conda_package/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/conda_package/tests/__init__.py -------------------------------------------------------------------------------- /conda_package/tests/test_cime_constants.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from mpas_tools.cime.constants import constants 4 | 5 | 6 | def test_cime_constants(e3sm_tag='master'): 7 | """ 8 | Parse relevant constants from CIME 9 | 10 | Parameters 11 | ---------- 12 | e3sm_tag : str, optional 13 | The E3SM tag to download constants from 14 | """ 15 | 16 | resp = requests.get( 17 | f'https://raw.githubusercontent.com/E3SM-Project/E3SM/{e3sm_tag}/' 18 | f'share/util/shr_const_mod.F90' 19 | ) 20 | 21 | text = resp.text 22 | 23 | text = text.split('\n') 24 | 25 | found = {} 26 | for constant in constants: 27 | found[constant] = False 28 | 29 | for line in text: 30 | constant, value = _parse_value(line) 31 | if constant is None: 32 | continue 33 | print(f'line: {line}') 34 | print(f'parsed: {constant} = {value}') 35 | if constant in constants: 36 | if isinstance(value, float): 37 | print(f'verifying {constant}') 38 | assert value == constants[constant] 39 | else: 40 | print(f'skipping verification for {constant}') 41 | 42 | found[constant] = True 43 | else: 44 | print('not in constants') 45 | 46 | print('') 47 | 48 | all_found = True 49 | for constant in found: 50 | if not found[constant]: 51 | print(f'{constant} was not found!') 52 | all_found = False 53 | 54 | assert all_found 55 | 56 | 57 | def _parse_value(line): 58 | if '::' not in line or '=' not in line: 59 | return None, None 60 | 61 | start = line.find('::') + 2 62 | end = line.find('=') 63 | 64 | key = line[start:end] 65 | line = line[end + 1 :] 66 | 67 | if '!' in line: 68 | line, _ = line.split('!', 1) 69 | 70 | line = line.replace('_R8', '').replace('_r8', '') 71 | 72 | try: 73 | value = float(line) 74 | except ValueError: 75 | value = line.strip() 76 | 77 | return key.strip(), value 78 | 79 | 80 | if __name__ == '__main__': 81 | test_cime_constants() 82 | -------------------------------------------------------------------------------- /conda_package/tests/test_conversion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import matplotlib 4 | 5 | from mpas_tools.io import write_netcdf 6 | from mpas_tools.mesh.conversion import convert, cull, mask 7 | 8 | from .util import get_test_data_file 9 | 10 | matplotlib.use('Agg') 11 | import xarray 12 | from geometric_features import read_feature_collection 13 | 14 | 15 | def test_conversion(): 16 | dsMesh = xarray.open_dataset( 17 | get_test_data_file('mesh.QU.1920km.151026.nc') 18 | ) 19 | dsMesh = convert(dsIn=dsMesh) 20 | write_netcdf(dsMesh, 'mesh.nc') 21 | 22 | dsMask = xarray.open_dataset(get_test_data_file('land_mask_final.nc')) 23 | dsCulled = cull(dsIn=dsMesh, dsMask=dsMask) 24 | write_netcdf(dsCulled, 'culled_mesh.nc') 25 | 26 | fcMask = read_feature_collection( 27 | get_test_data_file('Arctic_Ocean.geojson') 28 | ) 29 | dsMask = mask(dsMesh=dsMesh, fcMask=fcMask) 30 | write_netcdf(dsMask, 'antarctic_mask.nc') 31 | 32 | 33 | if __name__ == '__main__': 34 | test_conversion() 35 | -------------------------------------------------------------------------------- /conda_package/tests/test_signed_distance.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import numpy as np 4 | import xarray as xr 5 | from geometric_features import FeatureCollection 6 | 7 | from mpas_tools.cime.constants import constants 8 | from mpas_tools.io import write_netcdf 9 | from mpas_tools.mesh.creation.signed_distance import ( 10 | distance_from_geojson, 11 | mask_from_geojson, 12 | signed_distance_from_geojson, 13 | ) 14 | 15 | 16 | def test_signed_distance_from_geojson(): 17 | lon, lat, fc_mask, earth_radius = _get_lon_lat_fc() 18 | 19 | signed_distance = signed_distance_from_geojson( 20 | fc_mask, lon, lat, earth_radius, max_length=5.0 21 | ) 22 | 23 | ds = xr.Dataset() 24 | ds['lon'] = ('lon', lon) 25 | ds['lat'] = ('lat', lat) 26 | ds['signed_distance'] = (('lat', 'lon'), signed_distance) 27 | write_netcdf(ds, 'signed_distance.nc') 28 | 29 | 30 | def test_distance_from_geojson(): 31 | lon, lat, fc_mask, earth_radius = _get_lon_lat_fc() 32 | 33 | distance = distance_from_geojson( 34 | fc_mask, lon, lat, earth_radius, max_length=5.0 35 | ) 36 | 37 | ds = xr.Dataset() 38 | ds['lon'] = ('lon', lon) 39 | ds['lat'] = ('lat', lat) 40 | ds['distance'] = (('lat', 'lon'), distance) 41 | write_netcdf(ds, 'distance.nc') 42 | 43 | 44 | def test_mask_from_geojson(): 45 | lon, lat, fc_mask, earth_radius = _get_lon_lat_fc() 46 | 47 | mask = mask_from_geojson(fc_mask, lon, lat) 48 | 49 | ds = xr.Dataset() 50 | ds['lon'] = ('lon', lon) 51 | ds['lat'] = ('lat', lat) 52 | ds['mask'] = (('lat', 'lon'), mask) 53 | write_netcdf(ds, 'mask.nc') 54 | 55 | 56 | def _get_lon_lat_fc(): 57 | lon = np.linspace(-180, 180, 37) 58 | lat = np.linspace(-90, 90, 19) 59 | earth_radius = constants['SHR_CONST_REARTH'] 60 | 61 | feature = { 62 | 'type': 'Feature', 63 | 'properties': { 64 | 'name': 'North Atlantic', 65 | 'tags': '', 66 | 'object': 'region', 67 | 'component': 'ocean', 68 | 'author': 'Xylar Asay-Davis', 69 | }, 70 | 'geometry': { 71 | 'type': 'Polygon', 72 | 'coordinates': [ 73 | [ 74 | [-39.53161633291441, 57.08649995213068], 75 | [-69.30597933223675, 28.03212363054105], 76 | [-33.914428822900334, 13.4287331666755], 77 | [-15.9735991802836, 39.731395665957876], 78 | [-39.53161633291441, 57.08649995213068], 79 | ] 80 | ], 81 | }, 82 | } 83 | fc_mask = FeatureCollection() 84 | fc_mask.add_feature(feature) 85 | return lon, lat, fc_mask, earth_radius 86 | 87 | 88 | if __name__ == '__main__': 89 | test_signed_distance_from_geojson() 90 | test_distance_from_geojson() 91 | test_mask_from_geojson() 92 | -------------------------------------------------------------------------------- /conda_package/tests/util.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | def get_test_data_file(filename): 5 | """ 6 | Get the full path to a data file in the tests/data directory. 7 | 8 | Parameters 9 | ---------- 10 | filename : str 11 | The name of the data file. 12 | 13 | Returns 14 | ------- 15 | str 16 | The full relative path to the data file. 17 | """ 18 | 19 | local_path = os.path.join( 20 | 'mesh_tools', 'mesh_conversion_tools', 'test', filename 21 | ) 22 | repo_path = os.path.join('..', '..', local_path) 23 | if os.path.exists(local_path): 24 | return local_path 25 | elif os.path.exists(repo_path): 26 | return repo_path 27 | 28 | raise FileNotFoundError( 29 | f"Data file '{filename}' not found in expected locations: " 30 | f'{local_path} or {repo_path}' 31 | ) 32 | -------------------------------------------------------------------------------- /landice/mesh_tools_li/add_no_water_flux_around_boundary.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' 3 | This script marks all of the boundary edges in a domain as no-flux hydrology boundaries. 4 | ''' 5 | 6 | from __future__ import absolute_import, division, print_function, \ 7 | unicode_literals 8 | 9 | import netCDF4 10 | import numpy as np 11 | from optparse import OptionParser 12 | from datetime import datetime 13 | import sys 14 | 15 | print("== Gathering information. (Invoke with --help for more details. All arguments are optional)\n") 16 | parser = OptionParser() 17 | parser.description = __doc__ 18 | parser.add_option("-f", "--file", dest="inputFile", help="name of file to be modified.", default="landice_grid.nc", metavar="FILENAME") 19 | parser.add_option("-t", "--time", dest="time", help="time level to modify", default=0, type="int", metavar="FILENAME") 20 | for option in parser.option_list: 21 | if option.default != ("NO", "DEFAULT"): 22 | option.help += (" " if option.help else "") + "[default: %default]" 23 | options, args = parser.parse_args() 24 | 25 | 26 | print(" Input file: {}".format(options.inputFile)) 27 | print(" Time level: {}".format(options.time)) 28 | 29 | f=netCDF4.Dataset(options.inputFile, 'r+') 30 | nEdges = len(f.dimensions['nEdges']) 31 | cONe = f.variables['cellsOnEdge'][:] 32 | if not 'waterFluxMask' in f.variables: 33 | f.createVariable('waterFluxMask', 'i', ('Time','nEdges')) 34 | mask = f.variables['waterFluxMask'][options.time, :] 35 | 36 | 37 | mask[:] = 0 38 | for i in range(nEdges): 39 | if min(cONe[i, :]) == 0: 40 | mask[i] = 2 41 | f.variables['waterFluxMask'][options.time, :] = mask[:] 42 | 43 | 44 | # Update history attribute of netCDF file 45 | thiscommand = datetime.now().strftime("%a %b %d %H:%M:%S %Y") + ": " + " ".join(sys.argv[:]) 46 | if hasattr(f, 'history'): 47 | newhist = '\n'.join([thiscommand, getattr(f, 'history')]) 48 | else: 49 | newhist = thiscommand 50 | setattr(f, 'history', newhist ) 51 | 52 | f.close() 53 | 54 | print('\nMarking boundary edges completed.') 55 | -------------------------------------------------------------------------------- /landice/mesh_tools_li/adjust_thickness_at_false_ocean_cells.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' 3 | This script changes the designation of isolated cells inland from the grounding line that are wrongfully defined as 4 | floating ice (and thus part of the ocean) when using the ocean density to define grounded/floating cells, as done in li_mask_is_grounded_ice. 5 | Ocean and floating ice cells are flood filled from the edges of the domain, and any floating ice cells not in contact with the flood fill are 6 | identified. Thickness of these cells is then manually altered to enforce the designation of grounded ice. 7 | ''' 8 | import mpas_tools 9 | import numpy as np 10 | import xarray as xr 11 | from compass.landice.mesh import mpas_flood_fill 12 | from optparse import OptionParser 13 | import subprocess 14 | 15 | print("** Gathering information ...") 16 | parser = OptionParser() 17 | parser.add_option("-f", "--file", dest="file", metavar="FILE") 18 | options, args = parser.parse_args() 19 | 20 | f = xr.open_dataset(options.file, decode_times=False, decode_cf=False) 21 | cellsOnCell= f['cellsOnCell'][:,:].data 22 | nEdgesOnCell = f['nEdgesOnCell'][:].data 23 | thickness = f['thickness'][0,:].data 24 | bedTopography = f['bedTopography'][0,:].data 25 | cellsOnEdge = f['cellsOnEdge'][:,:].data 26 | 27 | groundedIceMask = ((thickness*910/1028+bedTopography)>0.0)*(thickness>0.0) 28 | floatingIceMask = ((thickness*910/1028+bedTopography)<=0.0)*(thickness>0.0) 29 | oceanMask = (thickness==0.0)*(bedTopography<0.0) 30 | landMask = (thickness==0.0)*(bedTopography>=0.0) 31 | 32 | seedMask = np.zeros((len(nEdgesOnCell),), 'float64') 33 | growMask = floatingIceMask + oceanMask 34 | 35 | ind = np.where(oceanMask==1)[0] 36 | for i in ind: 37 | for ii in range(nEdgesOnCell[i]): 38 | if (cellsOnCell[i,ii] == 0): 39 | seedMask[i] = 1 40 | 41 | print("**Flood Filling ...") 42 | 43 | keepMask = mpas_flood_fill(seedMask, growMask, cellsOnCell, nEdgesOnCell) 44 | 45 | ind = np.where(floatingIceMask==1)[0] 46 | for i in ind: 47 | if (keepMask[i] == 0): 48 | thickness[i] = -bedTopography[i] * 1028/910 + 1e-10 #thickness necessary to achieve grounded ice (small margin past exact flotation) 49 | 50 | print("**Saving ...") 51 | 52 | seedMask = seedMask.reshape(1,len(seedMask)) 53 | growMask = growMask.reshape(1,len(growMask)) 54 | keepMask = keepMask.reshape(1,len(keepMask)) 55 | thickness = thickness.reshape(1,len(thickness)) 56 | 57 | gm = xr.DataArray(growMask.astype('float64'),dims=('Time','nCells')) 58 | f['growMask'] = gm 59 | 60 | sm = xr.DataArray(seedMask.astype('float64'),dims=('Time','nCells')) 61 | f['seedMask'] = sm 62 | 63 | km = xr.DataArray(keepMask.astype('float64'),dims=('Time','nCells')) 64 | f['keepMask'] = km 65 | 66 | thk = xr.DataArray(thickness.astype('float64'),dims=('Time','nCells')) 67 | f['thickness'] = thk 68 | 69 | f.to_netcdf("modifiedThicknessDomain.nc") 70 | f.close() 71 | 72 | subprocess.run(["ncatted", "-a", "_FillValue,,d,,", "modifiedThicknessDomain.nc"]) 73 | -------------------------------------------------------------------------------- /landice/mesh_tools_li/misc/mpas_mesh_to_landice_ic_batch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #MSUB -l walltime=02:00:00 3 | #MSUB -l nodes=1 4 | #MSUB -j oe 5 | 6 | source ~/setup_gnu_env.sh 7 | 8 | # This script is a template for a batch script that will perform the various steps required 9 | # to go from a base MPAS mesh to a culled landice mesh with initial conditions. 10 | # It's main purpose is to be used on clusters with a batch system for situations 11 | # where the larger memory available on those machines is required. 12 | # In addition to setting the variables below, it is recommended to look over all the steps 13 | # and ensure they are happening in the proper order and with the correct flags for 14 | # your particular situation. 15 | 16 | 17 | # Location of MPAS-Tools repo 18 | TOOLS=/users/mhoffman/mpas/MPAS-Tools 19 | 20 | # Command used on the machine for running an executable 21 | RUNCMD="mpirun -n 1 " 22 | 23 | # The name of the mesh with which processing 24 | STARTMESH=mpas.nc 25 | 26 | # The name of the initial condition file from which initial conditions will be interpolated 27 | INTERPFILE=/usr/projects/climate/mhoffman/AIS_IC_data/Antarctica-1km.BISICLES.CISM-style.nc 28 | 29 | # Amount to translate the mesh in x and y 30 | SHIFTX=0.0 31 | SHIFTY=0.0 32 | 33 | # Projection to use for adding lat/lon values. See that script for options or to add new ones 34 | PROJ=ais-bedmap2 35 | 36 | # ========================== 37 | 38 | date 39 | 40 | # shift by some amount 41 | #$RUNCMD $TOOLS/grid_gen/planar_grid_transformations/translate_planar_grid.py -f $STARTMESH -x $SHIFTX -y $SHIFTY 42 | date 43 | 44 | # generate culling mask 45 | $RUNCMD $TOOLS/grid_gen/landice_grid_tools/define_cullMask.py -f $STARTMESH -m 4 # method 4 removed junk from near the edges 46 | date 47 | 48 | # Cull mesh 49 | $RUNCMD $TOOLS/grid_gen/mesh_conversion_tools/MpasCellCuller.x $STARTMESH culled1.nc 50 | date 51 | 52 | # Add lat/lon 53 | $RUNCMD $TOOLS/grid_gen/planar_grid_transformations/set_lat_lon_fields_in_planar_grid.py -f culled1.nc -p $PROJ 54 | date 55 | 56 | # convert to LI mesh - no reason to have many vertical levels yet since we are going to cull 57 | $RUNCMD $TOOLS/grid_gen/landice_grid_tools/create_landice_grid_from_generic_MPAS_grid.py -i culled1.nc -o landice_grid_full.nc -l 2 --beta 58 | date 59 | 60 | # Interpolate thickness 61 | $RUNCMD $TOOLS/grid_gen/landice_grid_tools/interpolate_cism_grid_to_mpas_grid.py -m landice_grid_full.nc -c $INTERPFILE --thickness-only 62 | date 63 | 64 | # generate culling mask 65 | $RUNCMD $TOOLS/grid_gen/landice_grid_tools/define_cullMask.py -f landice_grid_full.nc -m 2 66 | date 67 | 68 | # Cull mesh 69 | $RUNCMD $TOOLS/grid_gen/mesh_conversion_tools/MpasCellCuller.x landice_grid_full.nc culled2.nc 70 | date 71 | 72 | # Make LI mesh 73 | $RUNCMD $TOOLS/grid_gen/landice_grid_tools/create_landice_grid_from_generic_MPAS_grid.py -i culled2.nc -o landice_grid.nc -l 10 --beta 74 | date 75 | 76 | # Interpolate everything 77 | $RUNCMD $TOOLS/grid_gen/landice_grid_tools/interpolate_cism_grid_to_mpas_grid.py -m landice_grid.nc -c $INTERPFILE 78 | date 79 | 80 | echo "All done." 81 | -------------------------------------------------------------------------------- /landice/mesh_tools_li/set_von_mises_stress_map.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' 3 | Simple script for creating an input file with region-by-region values for 4 | the von Mises stress threshold. This can be used to assign optimal 5 | regional values identified through a tuning process. 6 | 7 | A region mask file is required as input. Values to assign are hardcoded 8 | below. There is not error checking that the number of values match the 9 | number of regions, so use with care. 10 | 11 | The script outputs a file called von_mises_calving_parameters.nc with the 12 | assigned regional values. 13 | 14 | Matt Hoffman, 9/19/2022 15 | ''' 16 | 17 | from __future__ import absolute_import, division, print_function, unicode_literals 18 | 19 | import sys 20 | import numpy as np 21 | from netCDF4 import Dataset 22 | from optparse import OptionParser 23 | import matplotlib.pyplot as plt 24 | 25 | parser = OptionParser(description=__doc__) 26 | parser.add_option("-n", dest="fileRegions", help="region file name.", metavar="FILENAME") 27 | options, args = parser.parse_args() 28 | 29 | f = Dataset(options.fileRegions, 'r') 30 | regionCellMasks = f.variables['regionCellMasks'][:] 31 | nRegions = len(f.dimensions['nRegions']) 32 | nCells = len(f.dimensions['nCells']) 33 | 34 | fout = Dataset("von_mises_calving_parameters.nc", 'w') 35 | fout.createDimension('nCells', nCells) 36 | fout.createDimension('Time', None) 37 | grdVM = fout.createVariable('groundedVonMisesThresholdStress', 'd', ('Time', 'nCells',)) 38 | fltVM = fout.createVariable('floatingVonMisesThresholdStress', 'd', ('Time', 'nCells',)) 39 | 40 | values=[ 41 | 125.0, 42 | 200.0, 43 | 150.0, 44 | 300.0, #300 45 | 46 | 200.0, #225? 47 | 350.0, # 400? 48 | 400.0, 49 | 125.0, # 130-400 50 | 51 | 300.0, #400? 52 | 300.0, #300-400 53 | 300.0, # 300 54 | 200.0, # 100? 55 | 56 | 125.0, 57 | 125.0,#? 58 | 125.0,#120-400 59 | 125.0,#125-300 60 | ] 61 | 62 | grdVM[:]=100.0e3 63 | fltVM[:]=100.0e3 64 | for r in range(nRegions): 65 | mask = np.nonzero(regionCellMasks[:,r] == 1)[0] 66 | grdVM[0, mask] = values[r] * 1000.0 67 | fltVM[0, mask] = values[r] * 1000.0 68 | 69 | fout.close() 70 | f.close() 71 | -------------------------------------------------------------------------------- /mesh_tools/create_SCRIP_files/create_scrip_mask_for_sufficiently_deep_ocean_mapping.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Script for defining mask of ocean cells that are deeper than a threshold. 4 | To be used for updating a scrip file so that it only remaps 5 | from ocean cells deeper than that threshold. 6 | The resulting mapping file can be used as an OCN2GLC_TF_SMAPNAME 7 | mapping file in E3SM. 8 | Note that config_2d_thermal_forcing_depth in the MPAS-Ocean namelist 9 | needs to match the depth used here! 10 | """ 11 | 12 | import argparse 13 | import sys 14 | from datetime import datetime 15 | from netCDF4 import Dataset 16 | 17 | parser = argparse.ArgumentParser( 18 | description=__doc__) 19 | parser.add_argument("-s", dest="scrip", 20 | required=True, 21 | help="scrip file to which to add mask") 22 | parser.add_argument("-m", dest="mpas", 23 | required=True, 24 | help="MPAS-Ocean mesh file") 25 | parser.add_argument("-d", dest="depth", 26 | required=True, 27 | help="depth threshold (m), should be a positive value", 28 | type=float) 29 | args = parser.parse_args() 30 | 31 | assert args.depth > 0.0, "'depth' argument should be a positive value" 32 | 33 | # open mesh file 34 | fmesh = Dataset(args.mpas, 'r') 35 | nCells = len(fmesh.dimensions['nCells']) 36 | bottomDepth = fmesh.variables['bottomDepth'][:] 37 | 38 | # identify cells shallower than target depth 39 | mask = bottomDepth > args.depth 40 | 41 | # insert mask into scrip file 42 | fscrip = Dataset(args.scrip, 'r+') 43 | if 'grid_imask' not in fscrip.variables: 44 | fscrip.createVariable('grid_imask', 'i', ('nCells',)) 45 | fscrip.variables['grid_imask'][:] = mask 46 | 47 | # Update history attribute of scrip netCDF file 48 | thiscommand = datetime.now().strftime("%a %b %d %H:%M:%S %Y") + ": " + " ".join(sys.argv[:]) 49 | if hasattr(fscrip, 'history'): 50 | newhist = '\n'.join([thiscommand, getattr(fscrip, 'history')]) 51 | else: 52 | newhist = thiscommand 53 | setattr(fscrip, 'history', newhist ) 54 | 55 | fmesh.close() 56 | fscrip.close() 57 | -------------------------------------------------------------------------------- /mesh_tools/grid_rotate/Makefile: -------------------------------------------------------------------------------- 1 | FC = $(shell nf-config --fc) 2 | FFLAGS = -O3 3 | FCINCLUDES = $(shell nf-config --fflags) 4 | RPATH_FLAGS = $(shell nf-config --flibs | grep -o -e '-L\S\+\( \|$$\)' | sed 's/^-L/-Wl,-rpath,/' | tr -d '\n') 5 | RPATH_FLAGS += $(shell nc-config --libs | grep -o -e '-L\S\+\( \|$$\)' | sed 's/^-L/-Wl,-rpath,/' | tr -d '\n') 6 | FCLIBS = -L$(shell nc-config --libdir) $(shell nf-config --flibs) $(RPATH_FLAGS) 7 | 8 | all: grid_rotate 9 | 10 | grid_rotate: grid_rotate.f90 11 | $(FC) grid_rotate.f90 -o grid_rotate $(FFLAGS) $(FCINCLUDES) $(FCLIBS) 12 | 13 | clean: 14 | rm grid_rotate 15 | -------------------------------------------------------------------------------- /mesh_tools/grid_rotate/mesh.ncl: -------------------------------------------------------------------------------- 1 | load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl" 2 | load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl" 3 | 4 | begin 5 | 6 | r2d = 57.2957795 ; radians to degrees 7 | 8 | maxedges = 6 9 | 10 | wks = gsn_open_wks("pdf","mesh") 11 | gsn_define_colormap(wks,"BlAqGrYeOrReVi200") 12 | 13 | f = addfile("grid.nc","r") 14 | 15 | xVertex = f->xVertex(:) 16 | yVertex = f->yVertex(:) 17 | zVertex = f->zVertex(:) 18 | verticesOnCell = f->verticesOnCell(:,:) 19 | verticesOnEdge = f->verticesOnEdge(:,:) 20 | x = f->lonCell(:) * r2d 21 | y = f->latCell(:) * r2d 22 | lonCell = f->lonCell(:) * r2d 23 | latCell = f->latCell(:) * r2d 24 | lonVertex = f->lonVertex(:) * r2d 25 | latVertex = f->latVertex(:) * r2d 26 | lonEdge = f->lonEdge(:) * r2d 27 | latEdge = f->latEdge(:) * r2d 28 | 29 | res = True 30 | res@gsnMaximize = True 31 | res@gsnSpreadColors = True 32 | 33 | res@sfXArray = x 34 | res@sfYArray = y 35 | 36 | res@cnFillOn = True 37 | res@cnFillMode = "RasterFill" 38 | res@cnLinesOn = False 39 | res@cnLineLabelsOn = False 40 | res@cnInfoLabelOn = True 41 | 42 | res@lbLabelAutoStride = True 43 | res@lbBoxLinesOn = False 44 | 45 | res@mpProjection = "CylindricalEquidistant" 46 | res@mpDataBaseVersion = "MediumRes" 47 | res@mpCenterLatF = 0. 48 | res@mpCenterLonF = 0. 49 | res@mpGridAndLimbOn = False 50 | res@mpOutlineOn = True 51 | res@mpFillOn = False 52 | res@mpPerimOn = False 53 | res@gsnFrame = False 54 | res@lbLabelBarOn = False 55 | 56 | h = f->areaCell(:) 57 | 58 | xpoly = new((/4/), "double") 59 | ypoly = new((/4/), "double") 60 | 61 | res@cnConstFLabelOn = False 62 | map = gsn_csm_contour_map(wks,h,res) 63 | 64 | lres = True 65 | lres@gsLineThicknessF = 0.10 66 | 67 | esizes = dimsizes(latEdge) 68 | ecx = new((/esizes(0),2/),double) 69 | ecy = new((/esizes(0),2/),double) 70 | do j=0,esizes(0)-1 71 | ecy(j,0) = latVertex(verticesOnEdge(j,0)-1) 72 | ecx(j,0) = lonVertex(verticesOnEdge(j,0)-1) 73 | ecy(j,1) = latVertex(verticesOnEdge(j,1)-1) 74 | ecx(j,1) = lonVertex(verticesOnEdge(j,1)-1) 75 | end do 76 | 77 | do j=0,esizes(0)-1 78 | if (abs(ecx(j,0) - ecx(j,1)) .gt. 180.0) then 79 | if (ecx(j,0) .gt. ecx(j,1)) then 80 | ecx(j,0) = ecx(j,0) - 360.0 81 | else 82 | ecx(j,1) = ecx(j,1) - 360.0 83 | end if 84 | end if 85 | end do 86 | 87 | do j=0,esizes(0)-1 88 | gsn_polyline(wks,map,ecx(j,:),ecy(j,:),lres) 89 | end do 90 | 91 | frame(wks) 92 | 93 | end 94 | 95 | -------------------------------------------------------------------------------- /mesh_tools/grid_rotate/namelist.input: -------------------------------------------------------------------------------- 1 | &input 2 | config_original_latitude_degrees = 0 3 | config_original_longitude_degrees = 0 4 | 5 | config_new_latitude_degrees = 0 6 | config_new_longitude_degrees = 0 7 | config_birdseye_rotation_counter_clockwise_degrees = 0 8 | / 9 | -------------------------------------------------------------------------------- /mesh_tools/hex_projection/Makefile: -------------------------------------------------------------------------------- 1 | FC = $(shell nf-config --fc) 2 | FFLAGS = -O3 3 | FCINCLUDES = $(shell nf-config --fflags) 4 | RPATH_FLAGS = $(shell nf-config --flibs | grep -o -e '-L\S\+\( \|$$\)' | sed 's/^-L/-Wl,-rpath,/' | tr -d '\n') 5 | RPATH_FLAGS += $(shell nc-config --libs | grep -o -e '-L\S\+\( \|$$\)' | sed 's/^-L/-Wl,-rpath,/' | tr -d '\n') 6 | FCLIBS = -L$(shell nc-config --libdir) $(shell nf-config --flibs) $(RPATH_FLAGS) 7 | 8 | OBJS = project_hexes.o \ 9 | mpas_geometry_utilities.o \ 10 | ph_utils.o \ 11 | ph_write_mesh.o \ 12 | projection_setup.o \ 13 | projections.o \ 14 | precision.o 15 | 16 | EXE = project_hexes 17 | 18 | $(EXE) : $(OBJS) 19 | $(FC) -o $@ $(OBJS) $(FCLIBS) 20 | 21 | project_hexes.o : mpas_geometry_utilities.o ph_utils.o ph_write_mesh.o projection_setup.o projections.o precision.o 22 | 23 | mpas_geometry_utilities.o : precision.o 24 | 25 | ph_utils.o: mpas_geometry_utilities.o precision.o 26 | 27 | ph_write_mesh.o : precision.o 28 | 29 | projection_setup.o : precision.o 30 | 31 | projections.o : projection_setup.o precision.o 32 | 33 | clean: 34 | $(RM) $(OBJS) *.mod $(EXE) 35 | 36 | 37 | %.o : %.mod 38 | 39 | %.o : %.f90 40 | $(RM) $@ $*.mod 41 | $(FC) $(FFLAGS) -c $< $(FCINCLUDES) 42 | -------------------------------------------------------------------------------- /mesh_tools/hex_projection/README: -------------------------------------------------------------------------------- 1 | MPAS-Atmosphere utility for creating regional meshes by projecting a 2 | Cartesian mesh of perfect hexagons to the sphere using standard map 3 | projections 4 | 5 | The current implementation uses a rectangular Cartesian mesh, with the 6 | corners slightly rounded, and projects this mesh to the sphere using a 7 | Lambert Conformal projection. Executing "make" with the included 8 | Makefile produces an executable named "project_hexes". The inputs 9 | to this executable are given in the ascii file "namelist.projections" 10 | (a standard Fortran namelist file). The inputs variables should be 11 | obvious from their names, and some further information is given in 12 | "Notes" below. The utility produces a netcdf file "mpas_hex_mesh.nc" 13 | describing the regional mesh in the form of a standard MPAS grid file, 14 | with the projection existing on the unit sphere (as is the case with 15 | all MPAS grid files for spheres). The utility also produces a 16 | graph.info file that serves as input to METIS to produce a partion 17 | file for use by MPAS as described in the MPAS-A Users Guide. 18 | 19 | Notes: 20 | 21 | The (x,y) extent of the domain is in meters on the earth-radius sphere, 22 | but as noted the MPAS grid file that is produced is on the unit sphere. 23 | 24 | Following WRF, the longitudinal center of the project is given by the 25 | namelist parameter "standard_longitude_degrees". The center of the 26 | projected mesh is given by the namelist parameter 27 | "reference_longitude_degrees". 28 | 29 | The hexagons are oriented pointing west-east. 30 | 31 | A python script is included that can plot the resulting mesh. 32 | An NCL script (a depricated language) is also provided to plot 33 | the mesh. 34 | 35 | The mesh can be moved and rotated to any place on the sphere using 36 | the MPAS grid_rotate tool (see the MPAS Users Guide). 37 | 38 | WCS, 4 March 2025 -------------------------------------------------------------------------------- /mesh_tools/hex_projection/mesh_plot.ncl: -------------------------------------------------------------------------------- 1 | load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl" 2 | load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl" 3 | load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/contributed.ncl" 4 | 5 | begin 6 | 7 | ;****************************************************************************** 8 | 9 | wks = gsn_open_wks("pdf","mesh_ncl_plot") 10 | 11 | f_in = addfile("mpas_hex_mesh.nc","r") 12 | 13 | ;****************************************************************************** 14 | 15 | res = True 16 | ; res@gsnMaximize = True 17 | res@gsnDraw = False 18 | res@gsnFrame = False 19 | res@gsnSpreadColors = True 20 | 21 | ; res@mpProjection = "CylindricalEquidistant" 22 | res@mpProjection = "Orthographic" 23 | res@mpDataBaseVersion = "MediumRes" 24 | res@mpCenterLatF = 38.5 25 | ; res@mpCenterLatF = 0.0 26 | res@mpCenterLonF = -97.5 27 | 28 | res@mpMinLonF = -157.5 29 | res@mpMaxLonF = -37.5 30 | res@mpMinLatF = 10. 31 | res@mpMaxLatF = 70. 32 | 33 | res@cnFillOn = True 34 | res@cnFillMode = "AreaFill" 35 | res@cnLinesOn = False 36 | ;res@cnLineLabelsOn = True 37 | ;res@cnLineThicknessF = 2. 38 | 39 | res@cnLevelSelectionMode = "ManualLevels" 40 | 41 | res@tiMainFontHeightF = 0.016 42 | res@tiMainString = "MPAS regional mesh" 43 | res@gsnLeftStringFontHeightF = 0.015 44 | res@gsnRightStringFontHeightF = 0.015 45 | 46 | ;res@lbLabelStride = 2 47 | 48 | ;-----1. contour for global z500 ------------------------------------------- 49 | 50 | ; gsn_define_colormap(wks,"WhiteBlueGreenYellowRed") 51 | ; gsn_define_colormap(wks,"BlAqGrYeOrReVi200") 52 | gsn_define_colormap(wks,"perc2_9lev") 53 | 54 | ;res@gsnSpreadColors = False 55 | ;res@gsnSpreadColorStart = 2 56 | ;res@gsnSpreadColorEnd = 201 57 | 58 | r2d = 180.D/(4.*atan(1.)) 59 | lat1d = f_in->latCell(:)*r2d 60 | lon1d = f_in->lonCell(:)*r2d 61 | 62 | res@sfXArray = lon1d 63 | res@sfYArray = lat1d 64 | 65 | 66 | ibdymask = f_in->bdyMaskCell 67 | bdymask = int2dble(ibdymask) 68 | nCells = dimsizes(lat1d) 69 | 70 | res@cnMinLevelValF = 0.5 71 | res@cnMaxLevelValF = 7.5 72 | res@cnLevelSpacingF = 1.0 73 | 74 | 75 | ; plot = gsn_csm_contour_map_ce(wks,bdymask,res) 76 | plot = gsn_csm_contour_map(wks,bdymask,res) 77 | draw(plot) 78 | frame(wks) 79 | 80 | 81 | end 82 | 83 | -------------------------------------------------------------------------------- /mesh_tools/hex_projection/namelist.projections: -------------------------------------------------------------------------------- 1 | &mesh 2 | cell_spacing_km = 15. 3 | mesh_length_x_km = 5403. 4 | mesh_length_y_km = 3183. 5 | earth_radius_km = 6378.14 6 | / 7 | &projection 8 | projection_type = "lambert_conformal" 9 | / 10 | &lambert_conformal 11 | reference_longitude_degrees = -97.5 12 | standard_longitude_degrees = -97.5, 13 | reference_latitude_degrees = 38.5 14 | standard_parallel_1_degrees = 38.5 15 | standard_parallel_2_degrees = 38.5 16 | / 17 | -------------------------------------------------------------------------------- /mesh_tools/hex_projection/precision.f90: -------------------------------------------------------------------------------- 1 | module precision 2 | 3 | use, intrinsic :: iso_fortran_env, dp=>real64 4 | 5 | end module precision 6 | -------------------------------------------------------------------------------- /mesh_tools/hex_projection/projection_setup.f90: -------------------------------------------------------------------------------- 1 | module projection_setup 2 | 3 | ! use, intrinsic :: iso_fortran_env, dp=>real64 4 | use precision 5 | 6 | real(dp) :: cell_spacing_km 7 | real(dp) :: mesh_length_x_km 8 | real(dp) :: mesh_length_y_km 9 | real(dp) :: earth_radius_km 10 | 11 | character(len=20) :: projection_type 12 | 13 | real(dp) :: reference_longitude_degrees 14 | real(dp) :: reference_latitude_degrees 15 | real(dp) :: standard_longitude_degrees 16 | real(dp) :: standard_parallel_1_degrees 17 | real(dp) :: standard_parallel_2_degrees 18 | 19 | namelist /mesh/ cell_spacing_km, mesh_length_x_km, mesh_length_y_km, earth_radius_km 20 | namelist /projection/ projection_type 21 | namelist /lambert_conformal/ reference_longitude_degrees, reference_latitude_degrees, & 22 | standard_longitude_degrees, & 23 | standard_parallel_1_degrees, standard_parallel_2_degrees 24 | 25 | contains 26 | 27 | subroutine read_namelist() 28 | 29 | open(unit=10,file='namelist.projections',status='old') 30 | read(10, nml=mesh) 31 | read(10, nml=projection) 32 | read(10, nml=lambert_conformal) 33 | 34 | end subroutine read_namelist 35 | 36 | end module projection_setup 37 | -------------------------------------------------------------------------------- /mesh_tools/merge_split_meshes/merge_grids.py: -------------------------------------------------------------------------------- 1 | ../../conda_package/mpas_tools/merge_grids.py -------------------------------------------------------------------------------- /mesh_tools/merge_split_meshes/split_grids.py: -------------------------------------------------------------------------------- 1 | ../../conda_package/mpas_tools/split_grids.py -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.5) 2 | project (mesh_conversion_tools) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") 5 | 6 | include_directories (netcdf-cxx-4.2 .) 7 | 8 | set(SOURCES netcdf_utils.cpp netcdf-cxx-4.2/ncvalues.cpp netcdf-cxx-4.2/netcdf.cpp) 9 | 10 | add_executable (MpasMeshConverter.x mpas_mesh_converter.cpp ${SOURCES}) 11 | target_link_libraries (MpasMeshConverter.x netcdf) 12 | 13 | add_executable (MpasCellCuller.x mpas_cell_culler.cpp ${SOURCES}) 14 | target_link_libraries (MpasCellCuller.x netcdf) 15 | 16 | add_executable (MpasMaskCreator.x mpas_mask_creator.cpp jsoncpp.cpp ${SOURCES}) 17 | target_link_libraries (MpasMaskCreator.x netcdf) 18 | 19 | install (TARGETS MpasMeshConverter.x MpasCellCuller.x MpasMaskCreator.x DESTINATION bin) 20 | -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools/Makefile: -------------------------------------------------------------------------------- 1 | #Assumes ${NETCDF} is defined to the root of the netcdf library 2 | 3 | #### titan instructions #### 4 | # module purge 5 | # module load gcc/4.9.3 6 | # module load cray-netcdf/3.6.2 7 | # printenv NETCDF_DIR 8 | # export NETCDF=$NETCDF_DIR 9 | # make 10 | 11 | #### edison instructions #### 12 | # In this file: 13 | # comment gnu, uncomment intel flags 14 | # change to: 15 | # CXX=CC 16 | # may need to unload parallel NetCDF and HDF5 libraries 17 | # to avoid g++ conflicts: 18 | # module unload python 19 | # then: 20 | # module load cray-netcdf 21 | # module load netcdf-cxx 22 | # export NETCDF=/usr/common/graphics/netcdf-cxx/4.2 23 | # make 24 | 25 | # gnu 26 | CXX ?= g++ 27 | CFLAGS ?= -O3 -std=c++0x -fopenmp -lstdc++ 28 | DFLAGS ?= -g -std=c++0x -D_DEBUG -fopenmp -lstdc++ 29 | 30 | # intel 31 | # CXX=icpc 32 | # CFLAGS= -O3 -std=c++0x -qopenmp -lstdc++ 33 | # DFLAGS= -g -std=c++0x -D_DEBUG -qopenmp -lstdc++ 34 | 35 | CONV_EXECUTABLE= MpasMeshConverter.x 36 | CULL_EXECUTABLE= MpasCellCuller.x 37 | MASK_EXECUTABLE= MpasMaskCreator.x 38 | 39 | ifneq (${NETCDF}, ) 40 | ifneq ($(shell which ${NETCDF}/bin/nc-config 2> /dev/null), ) 41 | LIBS = $(shell ${NETCDF}/bin/nc-config --libs) 42 | INCS = $(shell ${NETCDF}/bin/nc-config --cflags) 43 | else 44 | LIBS= -L${NETCDF}/lib 45 | LIBS += -lnetcdf 46 | INCS = -I${NETCDF}/include 47 | endif 48 | else ifneq ($(shell which nc-config 2> /dev/null), ) 49 | LIBS = $(shell nc-config --libs) 50 | INCS = $(shell nc-config --cflags) 51 | else 52 | LIBS= -L${NETCDF}/lib 53 | LIBS += -lnetcdf 54 | INCS = -I${NETCDF}/include 55 | endif 56 | 57 | INCS += -Inetcdf-cxx-4.2/ 58 | SRC = netcdf_utils.cpp netcdf-cxx-4.2/ncvalues.cpp netcdf-cxx-4.2/netcdf.cpp 59 | 60 | all: 61 | ${CXX} mpas_mesh_converter.cpp ${SRC} ${CFLAGS} -o ${CONV_EXECUTABLE} -I. ${INCS} ${LIBS} 62 | ${CXX} mpas_cell_culler.cpp ${SRC} ${CFLAGS} -o ${CULL_EXECUTABLE} ${INCS} ${LIBS} 63 | ${CXX} mpas_mask_creator.cpp ${SRC} jsoncpp.cpp ${CFLAGS} -o ${MASK_EXECUTABLE} -I. ${INCS} ${LIBS} 64 | 65 | debug: 66 | ${CXX} mpas_mesh_converter.cpp ${SRC} ${DFLAGS} -o ${CONV_EXECUTABLE} ${INCS} ${LIBS} 67 | ${CXX} mpas_cell_culler.cpp ${SRC} ${DFLAGS} -o ${CULL_EXECUTABLE} ${INCS} ${LIBS} 68 | ${CXX} mpas_mask_creator.cpp ${SRC} jsoncpp.cpp ${DFLAGS} -o ${MASK_EXECUTABLE} -I. ${INCS} ${LIBS} 69 | 70 | clean: 71 | rm -f grid.nc 72 | rm -f graph.info 73 | rm -f ${CONV_EXECUTABLE} ${CULL_EXECUTABLE} ${MASK_EXECUTABLE} 74 | 75 | -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools/edge.h: -------------------------------------------------------------------------------- 1 | 2 | class edge {/*{{{*/ 3 | public: 4 | int cell1, cell2; 5 | int vertex1, vertex2; 6 | int idx; 7 | 8 | edge() 9 | : cell1(-1), cell2(-1), vertex1(-1), vertex2(-1), idx(-1) { } 10 | 11 | struct edge_hasher {/*{{{*/ 12 | size_t operator()(const edge &edge_) const { 13 | uint32_t hash; 14 | size_t i, key[2] = { (size_t)edge_.vertex1, (size_t)edge_.vertex2 }; 15 | for(hash = i = 0; i < sizeof(key); ++i) { 16 | hash += ((uint8_t *)key)[i]; 17 | hash += (hash << 10); 18 | hash ^= (hash >> 6); 19 | } 20 | hash += (hash << 3); 21 | hash ^= (hash >> 11); 22 | hash += (hash << 15); 23 | return hash; 24 | } 25 | };/*}}}*/ 26 | 27 | bool operator==(const edge &e) const {/*{{{*/ 28 | return (vertex1 == e.vertex1) && (vertex2 == e.vertex2); 29 | }/*}}}*/ 30 | };/*}}}*/ 31 | 32 | 33 | -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools/netcdf-cxx-4.2/COPYRIGHT: -------------------------------------------------------------------------------- 1 | /*! \file 2 | The NetCDF Copyright. 3 | 4 | \page copyright Copyright 5 | 6 | Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 7 | 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 University 8 | Corporation for Atmospheric Research/Unidata. 9 | 10 | Portions of this software were developed by the Unidata Program at the 11 | University Corporation for Atmospheric Research. 12 | 13 | Access and use of this software shall impose the following obligations 14 | and understandings on the user. The user is granted the right, without 15 | any fee or cost, to use, copy, modify, alter, enhance and distribute 16 | this software, and any derivative works thereof, and its supporting 17 | documentation for any purpose whatsoever, provided that this entire 18 | notice appears in all copies of the software, derivative works and 19 | supporting documentation. Further, UCAR requests that the user credit 20 | UCAR/Unidata in any publications that result from the use of this 21 | software or in any product that includes this software, although this 22 | is not an obligation. The names UCAR and/or Unidata, however, may not 23 | be used in any advertising or publicity to endorse or promote any 24 | products or commercial entity unless specific written permission is 25 | obtained from UCAR/Unidata. The user also understands that 26 | UCAR/Unidata is not obligated to provide the user with any support, 27 | consulting, training or assistance of any kind with regard to the use, 28 | operation and performance of this software nor to provide the user 29 | with any updates, revisions, new versions or "bug fixes." 30 | 31 | THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR 32 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 33 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 34 | DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL, 35 | INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 36 | FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 37 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 38 | WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE. 39 | */ 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools/netcdf-cxx-4.2/README: -------------------------------------------------------------------------------- 1 | netcdfcpp.h the C++ interface 2 | 3 | netcdf.cpp the implementation of the interface, on top of the current 4 | C library interface 5 | 6 | nctst.cpp a test program for the interface that creates a netCDF file 7 | and then dumps out its contents in ASCII form to stdout. 8 | This example may also be helpful in understanding how the 9 | interface is intended to be used. 10 | 11 | example.c example of C code needed to create a small netCDF file 12 | 13 | example.cpp analogous example of C++ code needed to do the same thing 14 | 15 | Makefile makefile for building nctst 16 | 17 | ncvalues.cpp interface for auxilliary classes of typed arrays needed by 18 | netCDF interface; fairly simple 19 | 20 | ncvalues.cpp implementation of auxilliary classes of typed arrays needed by 21 | netCDF interface 22 | 23 | README this file 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools/netcdf-cxx-4.2/netcdf.hh: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools/test/land_mask_final.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/mesh_tools/mesh_conversion_tools/test/land_mask_final.nc -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools/test/mesh.QU.1920km.151026.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MPAS-Dev/MPAS-Tools/ed9538185bfef3053b39df9acf43f1162702275e/mesh_tools/mesh_conversion_tools/test/mesh.QU.1920km.151026.nc -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools_netcdf_c/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.5) 2 | project (mesh_conversion_tools) 3 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 5 | 6 | add_executable (MpasMeshConverter.x mpas_mesh_converter.cpp) 7 | target_link_libraries (MpasMeshConverter.x netcdf) 8 | 9 | add_executable (MpasCellCuller.x mpas_cell_culler.cpp) 10 | target_link_libraries (MpasCellCuller.x netcdf) 11 | 12 | #add_executable (MpasMaskCreator.x mpas_mask_creator.cpp jsoncpp.cpp) 13 | #target_link_libraries (MpasMaskCreator.x netcdf) 14 | 15 | install (TARGETS MpasMeshConverter.x MpasCellCuller.x DESTINATION bin) 16 | -------------------------------------------------------------------------------- /mesh_tools/mesh_conversion_tools_netcdf_c/edge.h: -------------------------------------------------------------------------------- 1 | 2 | class edge {/*{{{*/ 3 | public: 4 | int cell1, cell2; 5 | int vertex1, vertex2; 6 | int idx; 7 | 8 | edge() 9 | : cell1(-1), cell2(-1), vertex1(-1), vertex2(-1), idx(-1) { } 10 | 11 | struct edge_hasher {/*{{{*/ 12 | size_t operator()(const edge &edge_) const { 13 | uint32_t hash; 14 | size_t i, key[2] = { (size_t)edge_.vertex1, (size_t)edge_.vertex2 }; 15 | for(hash = i = 0; i < sizeof(key); ++i) { 16 | hash += ((uint8_t *)key)[i]; 17 | hash += (hash << 10); 18 | hash ^= (hash >> 6); 19 | } 20 | hash += (hash << 3); 21 | hash ^= (hash >> 11); 22 | hash += (hash << 15); 23 | return hash; 24 | } 25 | };/*}}}*/ 26 | 27 | bool operator==(const edge &e) const {/*{{{*/ 28 | return (vertex1 == e.vertex1) && (vertex2 == e.vertex2); 29 | }/*}}}*/ 30 | };/*}}}*/ 31 | 32 | 33 | -------------------------------------------------------------------------------- /mesh_tools/mpas2esmf/.gitignore: -------------------------------------------------------------------------------- 1 | mpas2esmf 2 | -------------------------------------------------------------------------------- /mesh_tools/mpas2esmf/Makefile: -------------------------------------------------------------------------------- 1 | FC = $(shell nc-config --fc) 2 | FCINCLUDES = $(shell nc-config --fflags) 3 | FCLIBS = $(shell nc-config --flibs) 4 | 5 | all: mpas2esmf.f90 6 | $(FC) -o mpas2esmf mpas2esmf.f90 ${FCINCLUDES} ${FCLIBS} 7 | 8 | clean: 9 | rm -f mpas2esmf read_mesh.mod write_desc.mod 10 | -------------------------------------------------------------------------------- /mesh_tools/mpas2esmf/README.md: -------------------------------------------------------------------------------- 1 | # mpas2esmf 2 | 3 | This tool generates ESMF and SCRIP files from an MPAS grid file. To avoid 4 | complications with CESM/CAM infrastructure tools, this tool should only be ran 5 | on grids that have a `sphere_radius = 1`. 6 | 7 | To build, ensure `nc-config` is in your $PATH and call `make`. 8 | 9 | By default, the ESMF and SCRIP NetCDF files created are 64BIT offset format. 10 | -------------------------------------------------------------------------------- /mesh_tools/periodic_hex/Makefile: -------------------------------------------------------------------------------- 1 | # IBM with Xlf compilers 2 | #FC = xlf90 3 | #CC = xlc 4 | #FFLAGS = -qrealsize=8 -g -C 5 | #CFLAGS = -g 6 | #LDFLAGS = -g -C 7 | 8 | # pgf90 9 | #FC = pgf90 10 | #CC = pgcc 11 | #FFLAGS = -r8 -O3 12 | #CFLAGS = -O3 13 | #LDFLAGS = -O3 14 | 15 | # gfortran 16 | FC = gfortran 17 | CC = gcc 18 | FFLAGS = -O3 -m64 -ffree-line-length-none -fdefault-real-8 -fconvert=big-endian 19 | CFLAGS = -O3 -m64 20 | LDFLAGS = -O3 -m64 21 | 22 | # ifort 23 | #FC = ifort 24 | #CC = icc 25 | #FFLAGS = -real-size 64 -O3 26 | #CFLAGS = -O3 27 | #LDFLAGS = -O3 28 | 29 | # absoft 30 | #FC = f90 31 | #CC = gcc 32 | #FFLAGS = -dp -O3 33 | #CFLAGS = -O3 34 | #LDFLAGS = -O3 35 | 36 | 37 | CPP = cpp -P -traditional 38 | CPPFLAGS = 39 | CPPINCLUDES = 40 | INCLUDES = -I$(NETCDF)/include 41 | 42 | # Specify NetCDF libraries, checking if netcdff is required (it will be present in v4 of netCDF) 43 | LIBS = -L$(NETCDF)/lib 44 | NCLIB = -lnetcdf 45 | NCLIBF = -lnetcdff 46 | ifneq ($(wildcard $(NETCDF)/lib/libnetcdff.*), ) # CHECK FOR NETCDF4 47 | LIBS += $(NCLIBF) 48 | endif # CHECK FOR NETCDF4 49 | LIBS += $(NCLIB) 50 | 51 | 52 | 53 | RM = rm -f 54 | 55 | ########################## 56 | 57 | .SUFFIXES: .F .o 58 | 59 | 60 | OBJS = periodic_grid.o \ 61 | module_cell_indexing.o \ 62 | module_write_netcdf.o 63 | 64 | all: periodic_grid 65 | 66 | periodic_grid.o: module_cell_indexing.o module_write_netcdf.o 67 | 68 | periodic_grid: $(OBJS) 69 | $(FC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) 70 | 71 | clean: 72 | $(RM) *.o *.mod periodic_grid 73 | 74 | .F.o: 75 | $(RM) $@ $*.mod 76 | $(CPP) $(CPPFLAGS) $(CPPINCLUDES) $< > $*.f90 77 | $(FC) $(FFLAGS) -c $*.f90 $(INCLUDES) 78 | $(RM) $*.f90 79 | -------------------------------------------------------------------------------- /mesh_tools/periodic_hex/namelist.input: -------------------------------------------------------------------------------- 1 | &periodic_grid 2 | nx = 500, 3 | ny = 500, 4 | dc = 10000., 5 | nVertLevels = 1, 6 | nTracers = 1, 7 | nproc = 2, 4, 8, 8 | / 9 | -------------------------------------------------------------------------------- /mesh_tools/periodic_quad/Makefile: -------------------------------------------------------------------------------- 1 | # IBM with Xlf compilers 2 | #FC = xlf90 3 | #CC = xlc 4 | #FFLAGS = -qrealsize=8 -g -C 5 | #CFLAGS = -g 6 | #LDFLAGS = -g -C 7 | 8 | # pgf90 9 | # FC = pgf90 10 | # CC = pgcc 11 | # FFLAGS = -r8 -O3 12 | # CFLAGS = -O3 13 | # LDFLAGS = -O3 14 | 15 | # ifort 16 | #FC = ifort 17 | #CC = icc 18 | #FFLAGS = -real-size 64 -O3 19 | #CFLAGS = -O3 20 | #LDFLAGS = -O3 21 | 22 | # absoft 23 | #FC = f90 24 | #CC = gcc 25 | #FFLAGS = -dp -O3 26 | #CFLAGS = -O3 27 | #LDFLAGS = -O3 28 | 29 | # gfortran 30 | FC = gfortran 31 | CC = gcc 32 | FFLAGS = -O3 -m64 -ffree-line-length-none -fdefault-real-8 -fconvert=big-endian 33 | CFLAGS = -O3 -m64 34 | LDFLAGS = -O3 -m64 35 | 36 | 37 | CPP = cpp -P -traditional 38 | CPPFLAGS = 39 | CPPINCLUDES = 40 | INCLUDES = -I$(NETCDF)/include 41 | 42 | # Specify NetCDF libraries, checking if netcdff is required (it will be present in v4 of netCDF) 43 | LIBS = -L$(NETCDF)/lib 44 | NCLIB = -lnetcdf 45 | NCLIBF = -lnetcdff 46 | ifneq ($(wildcard $(NETCDF)/lib/libnetcdff.*), ) # CHECK FOR NETCDF4 47 | LIBS += $(NCLIBF) 48 | endif # CHECK FOR NETCDF4 49 | LIBS += $(NCLIB) 50 | 51 | RM = rm -f 52 | 53 | ########################## 54 | 55 | .SUFFIXES: .F .o 56 | 57 | 58 | OBJS = periodic_grid.o \ 59 | module_cell_indexing.o \ 60 | module_write_netcdf.o 61 | 62 | all: periodic_grid 63 | 64 | periodic_grid.o: module_cell_indexing.o module_write_netcdf.o 65 | 66 | periodic_grid: $(OBJS) 67 | $(FC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) 68 | 69 | clean: 70 | $(RM) *.o *.mod periodic_grid 71 | 72 | .F.o: 73 | $(RM) $@ $*.mod 74 | $(CPP) $(CPPFLAGS) $(CPPINCLUDES) $< > $*.f90 75 | $(FC) $(FFLAGS) -c $*.f90 $(INCLUDES) 76 | $(RM) $*.f90 77 | -------------------------------------------------------------------------------- /mesh_tools/periodic_quad/namelist.input: -------------------------------------------------------------------------------- 1 | &periodic_grid 2 | nx = 50, 3 | ny = 50, 4 | dc = 100000., 5 | nVertLevels = 1, 6 | nTracers = 2, 7 | nVertexDegree = 4, 8 | nproc = 2, 4, 8, 9 | / 10 | -------------------------------------------------------------------------------- /mesh_tools/planar_grid_transformations/rotate_planar_grid.readme.txt: -------------------------------------------------------------------------------- 1 | The tool up one directory called grid_rotate can be used to rotate planar grids. (It works with either planar or spherical grids.) 2 | -------------------------------------------------------------------------------- /mesh_tools/planar_grid_transformations/scale_planar_grid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | This script scales the grid of an existing MPAS mesh by a scalar amount. 4 | """ 5 | from __future__ import absolute_import, division, print_function, unicode_literals 6 | 7 | import sys 8 | from netCDF4 import Dataset as NetCDFFile 9 | from optparse import OptionParser 10 | from datetime import datetime 11 | 12 | parser = OptionParser() 13 | parser.add_option("-f", "--file", dest="filename", help="Path to grid file", metavar="FILE") 14 | parser.add_option("-s", "--scale", dest="scale", help="linear scale factor", default=1.0, metavar="SCALE") 15 | options, args = parser.parse_args() 16 | 17 | if not options.filename: 18 | parser.error("A grid file is required.") 19 | 20 | print("Applying scale factor of: ", options.scale) 21 | 22 | scale = float(options.scale) 23 | 24 | grid = NetCDFFile(options.filename, 'a') 25 | 26 | grid.variables['xCell'][:] = grid.variables['xCell'][:] * scale 27 | grid.variables['yCell'][:] = grid.variables['yCell'][:] * scale 28 | grid.variables['zCell'][:] = grid.variables['zCell'][:] * scale 29 | 30 | grid.variables['xEdge'][:] = grid.variables['xEdge'][:] * scale 31 | grid.variables['yEdge'][:] = grid.variables['yEdge'][:] * scale 32 | grid.variables['zEdge'][:] = grid.variables['zEdge'][:] * scale 33 | 34 | grid.variables['xVertex'][:] = grid.variables['xVertex'][:] * scale 35 | grid.variables['yVertex'][:] = grid.variables['yVertex'][:] * scale 36 | grid.variables['zVertex'][:] = grid.variables['zVertex'][:] * scale 37 | 38 | grid.variables['dcEdge'][:] = grid.variables['dcEdge'][:] * scale 39 | grid.variables['dvEdge'][:] = grid.variables['dvEdge'][:] * scale 40 | 41 | grid.variables['areaCell'][:] = grid.variables['areaCell'][:] * scale**2 42 | grid.variables['areaTriangle'][:] = grid.variables['areaTriangle'][:] * scale**2 43 | grid.variables['kiteAreasOnVertex'][:] = grid.variables['kiteAreasOnVertex'][:] * scale**2 44 | 45 | # Update history attribute of netCDF file 46 | thiscommand = datetime.now().strftime("%a %b %d %H:%M:%S %Y") + ": " + " ".join(sys.argv[:]) 47 | if hasattr(grid, 'history'): 48 | newhist = '\n'.join([thiscommand, getattr(grid, 'history')]) 49 | else: 50 | newhist = thiscommand 51 | setattr(grid, 'history', newhist ) 52 | 53 | grid.close() 54 | 55 | print("Scale operation is complete.") 56 | -------------------------------------------------------------------------------- /mesh_tools/planar_hex/mpas_tools: -------------------------------------------------------------------------------- 1 | ../../conda_package/mpas_tools/ -------------------------------------------------------------------------------- /mesh_tools/planar_hex/planar_hex: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # -*- coding: utf-8 -*- 4 | import re 5 | import sys 6 | 7 | from mpas_tools.planar_hex import main 8 | 9 | if __name__ == '__main__': 10 | sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0]) 11 | sys.exit(main()) 12 | -------------------------------------------------------------------------------- /mesh_tools/points-mpas/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore object files. 2 | *.o 3 | 4 | # Ignore executable. 5 | PointsToMpas.x 6 | -------------------------------------------------------------------------------- /mesh_tools/points-mpas/Makefile: -------------------------------------------------------------------------------- 1 | #Assumes ${NETCDF} is defined to the root of the netcdf library 2 | 3 | CC=g++ 4 | CFLAGS= -O3 5 | EXECUTABLE= PointsToMpas.x 6 | 7 | NCINCDIR=${NETCDF}/include 8 | NCLIBDIR=${NETCDF}/lib 9 | 10 | all: 11 | ${CC} points-mpas.cpp ${CFLAGS} -o ${EXECUTABLE} -I${NCINCDIR} -L${NCLIBDIR} -lnetcdf_c++ -lnetcdf 12 | 13 | debug: 14 | ${CC} points-mpas.cpp -g -o ${EXECUTABLE} -I${NCINCDIR} -L${NCLIBDIR} -lnetcdf_c++ -lnetcdf 15 | 16 | clean: 17 | rm -f grid.nc 18 | rm -f graph.info 19 | rm -f ${EXECUTABLE} 20 | 21 | -------------------------------------------------------------------------------- /mesh_tools/points-mpas/Params: -------------------------------------------------------------------------------- 1 | Is the input Cartesian or Latitude-Longitude (0 - Cartesian, 1 - Lat-lon) 2 | 0 3 | Are the triangles base zero or base one? (0 - base 0, 1 - base 1) 4 | 0 5 | What is the radius of the sphere these points are defined on? 6 | 1.0 7 | How many vertical levels do you want in the output grid? 8 | 1 9 | How many tracers do you want in the output grid? 10 | 1 11 | What was the convergence criteria used to make this grid? 12 | 0.0 13 | Should this grid be vordraw compatible? 14 | 0 15 | -------------------------------------------------------------------------------- /mesh_tools/processor_decompositions/README: -------------------------------------------------------------------------------- 1 | Author: Doug Jacobsen 2 | Date: 02/12/13 3 | 4 | Usage: make_partition_files.py [options] 5 | 6 | Options: 7 | -h, --help show this help message and exit 8 | -f FILE, --file=FILE Path to grid file 9 | -m METIS, --metis=METIS 10 | Path or name of metis executable 11 | -p PROCS, --procs=PROCS 12 | Number of processors for decomposition 13 | -b BLOCKS, --blocks=BLOCKS 14 | Number of blocks for decomposition 15 | -w VAR, --weights=VAR 16 | Field to weight block partition file on. 17 | 18 | About: 19 | This script is used to create weighted and unweighted hierarchical 20 | decompositions for use with multiple blocks per MPI process in any MPAS core. 21 | 22 | As input, it takes a grid.nc file, the number of blocks to decompose, the 23 | number of processor to decompose, and the path to the metis executable or the 24 | name of the metis executable if it's in your path. 25 | 26 | Optionally, it takes the name of the variable in grid.nc that should be 27 | used to weight the block decomposition file with. 28 | 29 | After running the script, several files are generated which are described below: 30 | graph.info - Single processor graph decomposition file. 31 | (optional) weighted.graph.info - graph.info file used for creating weighted partition files. 32 | (weighted.)graph.info.part.BLOCKS - partition file that is weighted or unweighted and has BLOCKS number of partitions. 33 | block.graph.info - graph file of blocks. Equivalent to "blocksOnBlock" 34 | block.graph.info.part.PROCS - partition file that has PROCS number of partitions. 35 | 36 | These can be used in MPAS as the block decomposition file 37 | (graph.info.part.BLOCKS) and the proc decomposition file 38 | (block.graph.info.part.PROCS) to control the topology of blocks on MPI tasks. 39 | 40 | Additional graph.info.part files can be created by running the script 41 | multiple times, or my running metis on the graph.info file. 42 | 43 | Additional block.graph.info.part files can be created through the same 44 | process, but they can only be used in tandem with the corresponding 45 | graph.info.part.BLOCKS file. 46 | 47 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.5) 2 | enable_language(Fortran) 3 | project (seaice_grid_tools) 4 | 5 | list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) 6 | 7 | set (NETCDF_F90 "YES") 8 | find_package (NetCDF REQUIRED) 9 | 10 | message (STATUS "NETCDF_INCLUDES=${NETCDF_INCLUDES}") 11 | message (STATUS "NETCDF_LIBRARIES=${NETCDF_LIBRARIES}") 12 | 13 | include_directories(${NETCDF_INCLUDES}) 14 | add_executable (fix_regrid_output.exe fix_regrid_output.F90) 15 | target_link_libraries (fix_regrid_output.exe ${NETCDF_LIBRARIES}) 16 | 17 | install (TARGETS fix_regrid_output.exe DESTINATION bin) 18 | 19 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/Makefile: -------------------------------------------------------------------------------- 1 | #Assumes ${NETCDF} is defined to the root of the netcdf library 2 | 3 | F90 = gfortran 4 | 5 | F90FLAGS = -O2 6 | 7 | ifeq ($(NETCDF_FORTRAN_PATH),) 8 | INCS = -I${NETCDF}/include 9 | LIBS = -L${NETCDF}/lib -lnetcdf -lnetcdff 10 | else 11 | INCS = -I${NETCDF_FORTRAN_PATH}/include -I${NETCDF_C_PATH}/include 12 | LIBS = -L${NETCDF_FORTRAN_PATH}/lib -L${NETCDF_C_PATH}/lib -lnetcdf -lnetcdff 13 | endif 14 | 15 | all: 16 | ${F90} ${F90FLAGS} ${INCS} fix_regrid_output.F90 -o fix_regrid_output.exe ${LIBS} 17 | 18 | clean: 19 | rm fix_regrid_output.exe 20 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/cmake/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright $(git shortlog -s) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/cmake/README: -------------------------------------------------------------------------------- 1 | These files are https://github.com/jedbrown/cmake-modules -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/create_seaice_partitions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from mpas_tools.seaice.partition import create_partitions 3 | 4 | create_partitions() 5 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/extend_seaice_mask.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import argparse 3 | 4 | from mpas_tools.seaice.mask import extend_seaice_mask 5 | 6 | 7 | if __name__ == "__main__": 8 | 9 | parser = argparse.ArgumentParser(description='Extend the ice presence variable') 10 | 11 | parser.add_argument('-m', '--inputmesh', dest="filenameMesh", required=True, help='MPAS mesh file for source regridding mesh') 12 | parser.add_argument('-p', '--presence', dest="filenamePresence", required=True, help='File with ice presence') 13 | parser.add_argument('-e', '--extenddist', dest="extendDistance", required=True, help='distance (km) to extend ice present region', type=float) 14 | parser.add_argument('-u', '--unitsphere', dest="unitSphere", required=False, help='Is the mesh file a unit sphere', action='store_false') 15 | 16 | args = parser.parse_args() 17 | 18 | extend_seaice_mask(args.filenameMesh,args.filenamePresence,args.extendDistance,args.unitSphere) 19 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/gen_seaice_mesh_partition.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import argparse 3 | 4 | from mpas_tools.seaice.partition import gen_seaice_mesh_partition 5 | 6 | 7 | if __name__ == "__main__": 8 | 9 | # parsing 10 | parser = argparse.ArgumentParser(description='Create sea ice grid partition') 11 | 12 | parser.add_argument('-m', '--mesh', dest="meshFilename", required=True, help='MPAS mesh file') 13 | parser.add_argument('-r', '--regions', dest="regionFilename", required=True, help='region file') 14 | parser.add_argument('-n', '--nprocs', dest="nProcs", required=True, help='number of processors', type=int) 15 | parser.add_argument('-c', '--culler', dest="mpasCullerLocation", required=False, help='location of cell culler') 16 | parser.add_argument('-o', '--outprefix', dest="outputPrefix", required=False, help='output graph file prefic', default="graph.info") 17 | parser.add_argument('-p', '--plotting', dest="plotting", required=False, help='create diagnostic plotting file of partitions', action='store_true') 18 | parser.add_argument('-g', '--metis', dest="metis", required=False, help='name of metis utility', default="gpmetis") 19 | parser.add_argument('-e', '--equatorcull', dest="cullEquatorialRegion", required=False, help='create diagnostic plotting file of partitions', action='store_true') 20 | 21 | args = parser.parse_args() 22 | 23 | gen_seaice_mesh_partition(args.meshFilename, args.regionFilename, args.nProcs, args.mpasCullerLocation, args.outputPrefix, args.plotting, args.metis, args.cullEquatorialRegion) 24 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/gen_seaice_regions_latitude_bands.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import argparse 4 | import numpy as np 5 | from netCDF4 import Dataset 6 | import math 7 | 8 | radiansToDegrees = 180.0 / math.pi 9 | 10 | # parsing 11 | parser = argparse.ArgumentParser(description='Create partition regions based on latitude bands') 12 | 13 | parser.add_argument('-m', '--mesh', dest="meshFilename", required=True, help='MPAS mesh file') 14 | parser.add_argument('-r', '--regions', dest="regionFilename", required=True, help='output region file') 15 | parser.add_argument('-l', '--latitudes', dest="latitudes", required=False, help='latitude band limits degrees not including north/south poles', nargs="+", type=float) 16 | 17 | args = parser.parse_args() 18 | 19 | # required arguments 20 | meshFilename = args.meshFilename 21 | regionFilename = args.regionFilename 22 | if (args.latitudes is None): 23 | latitudes = np.array([-60.0,60.0]) 24 | else: 25 | latitudes = np.array(sorted(args.latitudes)) 26 | 27 | 28 | # load mesh file 29 | mesh = Dataset(meshFilename,"r") 30 | nCells = len(mesh.dimensions["nCells"]) 31 | latCell = mesh.variables["latCell"][:] 32 | mesh.close() 33 | 34 | 35 | # region variable 36 | region = np.zeros(nCells,dtype="i") 37 | 38 | nRegions = len(latitudes)+1 39 | 40 | latitudeMin = np.zeros(nRegions) 41 | latitudeMax = np.zeros(nRegions) 42 | 43 | latitudeMin[0] = -100.0 44 | latitudeMax[0] = latitudes[0] 45 | latitudeMin[-1] = latitudes[-1] 46 | latitudeMax[-1] = 100.0 47 | 48 | for iRegion in range(1,nRegions-1): 49 | latitudeMin[iRegion] = latitudes[iRegion-1] 50 | latitudeMax[iRegion] = latitudes[iRegion] 51 | 52 | print("nRegions: ", nRegions) 53 | print("latitudeMin: ", latitudeMin) 54 | print("latitudeMax: ", latitudeMax) 55 | 56 | for iRegion in range(0,nRegions): 57 | for iCell in range(0,nCells): 58 | if (latCell[iCell] * radiansToDegrees >= latitudeMin[iRegion] and 59 | latCell[iCell] * radiansToDegrees < latitudeMax[iRegion]): 60 | region[iCell] = iRegion 61 | 62 | # output regions 63 | regionFile = Dataset(regionFilename,"w",format="NETCDF3_CLASSIC") 64 | 65 | regionFile.nRegions = nRegions 66 | 67 | regionFile.createDimension("nCells",nCells) 68 | 69 | regionVar = regionFile.createVariable("region","i",dimensions=["nCells"]) 70 | regionVar[:] = region[:] 71 | 72 | regionFile.close() 73 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/make_regions_file.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import argparse 3 | 4 | from mpas_tools.seaice.regions import make_regions_file 5 | 6 | 7 | if __name__ == "__main__": 8 | 9 | # input parsing 10 | parser = argparse.ArgumentParser(description='Make a partition regions file.') 11 | 12 | parser.add_argument('-p', '--presence', dest="filenameIcePresent", required=True, help='ice presence file') 13 | parser.add_argument('-m', '--mesh', dest="filenameMesh", required=True, help='MPAS mesh file') 14 | # region type options: "two_region_eq", "three_region", "three_region_eq", "five_region_eq" 15 | parser.add_argument('-t', '--type', dest="regionType", required=True, help='region type') 16 | parser.add_argument('-v', '--varname', dest="varname", required=True, help='presence var name') 17 | parser.add_argument('-o', '--output', dest="filenameOut", required=True, help='output regions file') 18 | parser.add_argument('-l', '--limit', dest="limit", required=False, default=0.5, type=float, help='presence region limit') 19 | 20 | args = parser.parse_args() 21 | 22 | make_regions_file(args.filenameIcePresent, args.filenameMesh, args.regionType, args.varname, args.limit, args.filenameOut) 23 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/mpas_tools: -------------------------------------------------------------------------------- 1 | ../../conda_package/mpas_tools/ -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/prepare_seaice_partitions.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from mpas_tools.seaice.partition import prepare_partitions 3 | 4 | prepare_partitions() 5 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/regrid_to_other_mesh.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import argparse 3 | 4 | from mpas_tools.seaice.regrid import regrid_to_other_mesh 5 | 6 | 7 | if __name__ == "__main__": 8 | 9 | # parsing input 10 | parser = argparse.ArgumentParser(description='Regrid sea ice presence to other meshes.') 11 | 12 | parser.add_argument('-i', '--inputmesh', dest="meshFilenameSrc", required=True, help='MPAS mesh file for source regridding mesh') 13 | parser.add_argument('-p', '--presence', dest="filenameData", required=True, help='Input ice presence file for source mesh') 14 | parser.add_argument('-m', '--outputmesh', dest="meshFilenameDst", required=True, help='MPAS mesh file for destination regridding mesh') 15 | parser.add_argument('-o', '--output', dest="filenameOut", required=True, help='Output ice presence file for destination mesh') 16 | 17 | args = parser.parse_args() 18 | 19 | regrid_to_other_mesh(args.meshFilenameSrc, args.filenameData, args.meshFilenameDst, args.filenameOut) 20 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/rescale_mesh.py: -------------------------------------------------------------------------------- 1 | from netCDF4 import Dataset 2 | import math 3 | import argparse 4 | 5 | parser = argparse.ArgumentParser(description='Set mesh radius') 6 | 7 | parser.add_argument('-m', '--meshFilename', dest="meshFilename", required=True, help='MPAS mesh file for resizing') 8 | parser.add_argument('-r', '--sphereRadius', dest="sphereRadius", help='New sphere radius (m)') 9 | 10 | args = parser.parse_args() 11 | 12 | 13 | 14 | filein = Dataset(args.meshFilename,"a") 15 | 16 | oldSphereRadius = filein.sphere_radius 17 | 18 | if (args.sphereRadius == None): 19 | sphereRadius = 6371229.0 20 | else: 21 | sphereRadius = args.sphereRadius 22 | 23 | rescale = sphereRadius / oldSphereRadius 24 | rescale2 = math.pow(rescale,2) 25 | 26 | filein.sphere_radius = sphereRadius 27 | 28 | nCells = len(filein.dimensions["nCells"]) 29 | 30 | xCell = filein.variables["xCell"]; 31 | yCell = filein.variables["yCell"]; 32 | zCell = filein.variables["zCell"]; 33 | xCell[:] *= rescale 34 | yCell[:] *= rescale 35 | zCell[:] *= rescale 36 | 37 | xEdge = filein.variables["xEdge"]; 38 | yEdge = filein.variables["yEdge"]; 39 | zEdge = filein.variables["zEdge"]; 40 | xEdge[:] *= rescale 41 | yEdge[:] *= rescale 42 | zEdge[:] *= rescale 43 | 44 | xVertex = filein.variables["xVertex"]; 45 | yVertex = filein.variables["yVertex"]; 46 | zVertex = filein.variables["zVertex"]; 47 | xVertex[:] *= rescale 48 | yVertex[:] *= rescale 49 | zVertex[:] *= rescale 50 | 51 | dcEdge = filein.variables["dcEdge"]; 52 | dvEdge = filein.variables["dvEdge"]; 53 | dcEdge[:] *= rescale 54 | dvEdge[:] *= rescale 55 | 56 | areaCell = filein.variables["areaCell"]; 57 | areaTriangle = filein.variables["areaTriangle"]; 58 | kiteAreasOnVertex = filein.variables["kiteAreasOnVertex"]; 59 | areaCell[:] *= rescale 60 | areaTriangle[:] *= rescale 61 | kiteAreasOnVertex[:] *= rescale 62 | 63 | filein.close() 64 | -------------------------------------------------------------------------------- /mesh_tools/seaice_grid_tools/seaice_mesh.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | 4 | from mpas_tools.seaice.mesh import make_mpas_scripfile_on_cells 5 | 6 | if __name__ == "__main__": 7 | 8 | if (len(sys.argv) != 4): 9 | print("Usage: seaice_mesh.py meshFilename, scripFilename, title") 10 | sys.exit() 11 | 12 | meshFilename = sys.argv[1] 13 | scripFilename = sys.argv[2] 14 | title = sys.argv[3] 15 | 16 | make_mpas_scripfile_on_cells(meshFilename, scripFilename, title) 17 | -------------------------------------------------------------------------------- /ocean/coastline_alteration/add_critical_land_blockages_to_mask.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Add transects that identify critical regions where narrow strips of land block 4 | ocean flow. These are, essentially, the opposite of critical passages, which 5 | must remain open for ocean flow. 6 | """ 7 | 8 | from mpas_tools.ocean.coastline_alteration import ( 9 | main_add_critical_land_blockages 10 | ) 11 | 12 | if __name__ == '__main__': 13 | main_add_critical_land_blockages() 14 | -------------------------------------------------------------------------------- /ocean/coastline_alteration/add_land_locked_cells_to_mask.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Find ocean cells that are land-locked, and alter the cell 4 | mask so that they are counted as land cells. 5 | """ 6 | 7 | from mpas_tools.ocean.coastline_alteration import ( 8 | main_add_land_locked_cells_to_mask 9 | ) 10 | 11 | if __name__ == '__main__': 12 | main_add_land_locked_cells_to_mask() 13 | -------------------------------------------------------------------------------- /ocean/coastline_alteration/mpas_tools: -------------------------------------------------------------------------------- 1 | ../../conda_package/mpas_tools/ -------------------------------------------------------------------------------- /ocean/coastline_alteration/widen_transect_edge_masks.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """ 3 | Alter transects to be at least two cells wide. This is used for critical 4 | passages, to avoid sea ice blockage. Specifically, mark cells on both sides 5 | of each transect edge mask as a water cell. 6 | """ 7 | from mpas_tools.ocean.coastline_alteration import ( 8 | main_widen_transect_edge_masks 9 | ) 10 | 11 | if __name__ == '__main__': 12 | main_widen_transect_edge_masks() 13 | -------------------------------------------------------------------------------- /ocean/moc_southern_boundary_extractor/moc_southern_boundary_extractor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | ''' 4 | This script takes a mesh file (-m flag) and a file with MOC regions masks 5 | (-f flag) produce by the MPAS mask creator. The script produces a copy of 6 | the contents of the MOC mask file, adding transects that mark the southern 7 | boundary of each region in a file indicated with the -o flag. The transect 8 | is applied only to vertices and edges, not cells, because the need for southern 9 | boundary transect data on cells is not foreseen. 10 | ''' 11 | 12 | from mpas_tools.ocean.moc import ( 13 | moc_southern_boundary_extractor 14 | ) 15 | 16 | if __name__ == '__main__': 17 | moc_southern_boundary_extractor() 18 | -------------------------------------------------------------------------------- /ocean/moc_southern_boundary_extractor/mpas_tools: -------------------------------------------------------------------------------- 1 | ../../conda_package/mpas_tools/ -------------------------------------------------------------------------------- /ocean/performance_testing/README: -------------------------------------------------------------------------------- 1 | This automated performance testing suite was created by Divya Jaganathan for 2 | the Parallel Computing Summer Research Institute, 2018, with guidance from Mark 3 | Petersen, LANL. 4 | 5 | To run a performance test, start in any MPAS-Ocean run directory and add links to: 6 | - ocean_model 7 | - metis 8 | - from this directory: 9 | submit_performance_test_to_queue.py 10 | performance_test.py 11 | plot_from_files.py 12 | 13 | There are three ways to run this testing suite: 14 | 15 | 1. From a front end node, this command will submit a single job to the queue, of the size required. 16 | ./submit_performance_test_to_queue.py -M 128 -m 16 -r EC60to30 17 | 18 | 2. From a compute node, run this directly 19 | ./performance_test.py 20 | 21 | 3. The above steps creates plots with just those tests. After running several jobs, 22 | the data can be combined into a single plot with plot_from_files.py. This file is case specific, and 23 | requires the user to alter lines by hand. 24 | -------------------------------------------------------------------------------- /ocean/performance_testing/plot_from_files.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Name: plot_from_files.py 5 | Author: Divya Jaganathan 6 | Date: 26 July, 2018 7 | 8 | Plots a single plot of different performance curves from different performance_data text files in a folder 9 | 10 | """ 11 | 12 | import glob 13 | import matplotlib 14 | matplotlib.use('agg') 15 | import numpy as np 16 | import matplotlib.pyplot as plt 17 | import subprocess 18 | 19 | path = "/lustre/scratch2/turquoise/divjag2005/case_runs/performance_results_4096/*.txt" 20 | 21 | files = glob.glob(path) 22 | files = [files[4], files[0], files[1], files[3], files[2]] 23 | num_files = len(files) 24 | print(num_files) 25 | 26 | no_res_in_a_file = 9 27 | file_counter = 0 28 | 29 | array_x = np.zeros(shape=(num_files, no_res_in_a_file)) 30 | array_y = np.zeros(shape=(num_files, no_res_in_a_file)) 31 | 32 | colors = ["g", "k", "m", "r", "b"] 33 | labels = [ 34 | "uniform 60km", 35 | "variable 60to30km", 36 | "uniform 30km", 37 | "variable 60to15km", 38 | "uniform 15km"] 39 | 40 | 41 | for file in files: 42 | 43 | f = open(file, 'r') 44 | ob = f.read().split('\n') 45 | num_lines = len(ob) - 1 46 | line_counter = 6 47 | i = 0 48 | rank_column = 0 49 | SYPD_column = 7 50 | 51 | while line_counter < num_lines: 52 | array_x[file_counter][i] = ob[line_counter].split('\t')[rank_column] 53 | array_y[file_counter][i] = ob[line_counter].split('\t')[SYPD_column] 54 | line_counter = line_counter + 1 55 | i = i + 1 56 | 57 | font = {'weight': 'bold', 58 | 'size': '14'} 59 | 60 | matplotlib.rc('font', **font) 61 | plt.loglog(array_x[file_counter][0:i - 62 | 1], array_y[file_counter][0:i - 63 | 1], '-o', color=colors[file_counter], label="%s" % 64 | labels[file_counter]) 65 | perfect = (array_y[file_counter][i - 1] / 66 | array_x[file_counter][i - 1]) * array_x[file_counter][0:i - 1] 67 | plt.loglog( 68 | array_x[file_counter][0:i - 1], 69 | perfect, 70 | '--', 71 | color=colors[file_counter]) 72 | file_counter = file_counter + 1 73 | f.close() 74 | 75 | plt.xlabel('Number of MPI ranks', fontsize=14, weight='bold') 76 | plt.ylabel('SYPD', fontsize=14, weight='bold') 77 | plt.title(' 36 Core Broadwell (No HT)', fontsize=14, weight='bold') 78 | plt.xlim((10, 10000)) 79 | plt.ylim((0.05, 4000)) 80 | plt.tight_layout() 81 | plt.grid() 82 | plt.legend(title='resolution', loc='upper left') 83 | plt.savefig('result.png') 84 | -------------------------------------------------------------------------------- /ocean/performance_testing/weights/generate_graph.info_with_wgts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Name: generate_graph.info_with_wgts.py 5 | Author: Divya Jaganathan 6 | Date: 17 July, 2018 7 | 8 | Assigns vertex weight to each horizontal cell in graph.info (in gpmetis format) 9 | Reads: , 10 | Writes: graph.info_with_wgts_ 11 | 12 | Flags(s) in call-command: 13 | -x or --vertex_weight=, default=0.0 14 | -d or --data_file=, default=init.nc 15 | -g or --graph_file=, default=graph.info 16 | 17 | """ 18 | 19 | import numpy as np 20 | import netCDF4 as nc4 21 | from netCDF4 import MFDataset 22 | import argparse 23 | 24 | parser = \ 25 | argparse.ArgumentParser(description=__doc__, 26 | formatter_class=argparse.RawTextHelpFormatter) 27 | parser.add_argument( 28 | "-x", 29 | "--vertex_weight", 30 | dest="vertex_weight", 31 | help="Exponent factor in the weighing function defining dependence on depth (maxLevelCell)", 32 | default=0.0) 33 | 34 | parser.add_argument( 35 | "-d", 36 | "--data_file", 37 | dest="data_filename", 38 | help="File containing the maxLevelCell data (Default: init.nc)", 39 | default="init.nc") 40 | 41 | parser.add_argument( 42 | "-g", 43 | "--graph_file", 44 | dest="graph_filename", 45 | help="Unweighed graph file (Default: graph.info)", 46 | default="graph.info") 47 | 48 | 49 | args = parser.parse_args() 50 | 51 | depth_dependence_factor_x = float(args.vertex_weight) 52 | graph_filename = args.graph_filename 53 | data_filename = args.data_filename 54 | 55 | file = MFDataset(data_filename) 56 | 57 | levels = file.variables['maxLevelCell'][:] 58 | 59 | minimum = np.amin(levels) 60 | 61 | ratio = np.divide(levels, minimum) 62 | weights = np.ceil((np.float_power(ratio, depth_dependence_factor_x))) 63 | weights = weights.astype(int) 64 | file.close() 65 | 66 | filename = "graph.info_with_wgts_" + str(depth_dependence_factor_x) 67 | fr = open(graph_filename, 'r') 68 | fw = open(filename, 'w') 69 | 70 | counter = -1 71 | 72 | for line in fr: 73 | if counter == -1: 74 | temp = line.split("\n", 1)[0] 75 | # 010 indicates that the graph.info file is formatted to include the 76 | # cell weights 77 | fw.write("%s 010 \n" % temp) 78 | else: 79 | temp = line.split("\n", 1)[0] 80 | fw.write("%d %s \n" % (weights[counter], temp)) 81 | counter = counter + 1 82 | 83 | fr.close() 84 | fw.close() 85 | -------------------------------------------------------------------------------- /ocean/smooth_topo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.5) 2 | enable_language(Fortran) 3 | project (ocean_smooth_topo) 4 | 5 | list (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) 6 | 7 | set (NETCDF_F90 "YES") 8 | find_package (NetCDF REQUIRED) 9 | 10 | message (STATUS "NETCDF_INCLUDES=${NETCDF_INCLUDES}") 11 | message (STATUS "NETCDF_LIBRARIES=${NETCDF_LIBRARIES}") 12 | 13 | include_directories(${NETCDF_INCLUDES}) 14 | 15 | add_executable (ocean_smooth_topo_skip_land_ice smooth_topo_skip_land_ice.F90) 16 | target_link_libraries (ocean_smooth_topo_skip_land_ice ${NETCDF_LIBRARIES}) 17 | 18 | add_executable (ocean_smooth_topo_before_init smooth_topo_before_init.F90) 19 | target_link_libraries (ocean_smooth_topo_before_init ${NETCDF_LIBRARIES}) 20 | 21 | add_executable (ocean_smooth_topo_before_init_skip_land_ice smooth_topo_before_init_skip_land_ice.F90) 22 | target_link_libraries (ocean_smooth_topo_before_init_skip_land_ice ${NETCDF_LIBRARIES}) 23 | 24 | install (TARGETS ocean_smooth_topo_skip_land_ice ocean_smooth_topo_before_init ocean_smooth_topo_before_init_skip_land_ice DESTINATION bin) 25 | -------------------------------------------------------------------------------- /ocean/smooth_topo/README: -------------------------------------------------------------------------------- 1 | Authors: Adrian Turner, Mat Maltrud 2 | 3 | Tools for smoothing bathymetry in an MPAS-Ocean with a Gaussian filter with a 4 | characteristic length scale (stdDeviation) and cut-off distance 5 | (distanceLimit). Smoothing is applied over a given number of iterations 6 | (numSmoothingPasses). The tools do not currently work on meshes without 7 | ice-shelf cavities. 8 | 9 | The smooth_topo_skip_land_ice tool can be applied to topography after an 10 | initial condition has been created. The smoothing is only applied if the 11 | original maxLevelCell is deeper than a given threshold (minLevelForSmoothing) 12 | and ice-shelf cavities are ignored. 13 | 14 | The smooth_topo_before_init tool is used to smooth topography data on the MPAS 15 | mesh before an initial condition has been created. 16 | 17 | An example namelist file (smooth_depth_in) is: 18 | 19 | &smooth 20 | filename_depth_in = "mpaso.IcoswISC30E3r2.20230901.nc" 21 | filename_depth_out = "smooth.IcoswISC30E3r2.r200e100.1pass.min5.skipLandIce.231115.nc" 22 | filename_mpas_mesh = "mpaso.IcoswISC30E3r2.20230901.nc" 23 | distanceLimit = 200. 24 | stdDeviation = 100. 25 | numSmoothingPasses = 1 26 | minLevelForSmoothing = 5 27 | / 28 | 29 | The minLevelForSmoothing namelist option only applies to 30 | smooth_topo_skip_land_ice. 31 | -------------------------------------------------------------------------------- /ocean/smooth_topo/cmake/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright $(git shortlog -s) 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, this 11 | list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /ocean/smooth_topo/cmake/README: -------------------------------------------------------------------------------- 1 | These files are from https://github.com/jedbrown/cmake-modules 2 | -------------------------------------------------------------------------------- /operators/mpas_tools: -------------------------------------------------------------------------------- 1 | ../conda_package/mpas_tools -------------------------------------------------------------------------------- /operators/vector_reconstruction.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Extract Cartesian (X, Y, Z), zonal and meridional components of an MPAS vector 5 | field, given the field on edge normals. 6 | 7 | This tool requires that the field 'coeffs_reconstruct' has been saved to a 8 | NetCDF file. The simplest way to do this is to include the following stream 9 | in a forward run: 10 | 11 | 16 | 17 | 18 | 19 | 20 | and run the model for one time step. 21 | 22 | """ 23 | from mpas_tools.vector.reconstruct import main 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | -------------------------------------------------------------------------------- /output_processing/decomposition_fields/README: -------------------------------------------------------------------------------- 1 | Author: Doug Jacobsen 2 | Date: 12/17/2013 3 | 4 | About: 5 | This script is used to help visualize decompositions of an MPAS mesh. 6 | It appends to the grid file three arrays. 7 | cellDecomposition 8 | triangleDecomposition 9 | edgeDecomposition 10 | 11 | Usage: decomposition_fields.py [options] 12 | 13 | Options: 14 | -h, --help show this help message and exit 15 | -f FILE, --file=FILE Path to grid file 16 | -d DECOMP, --decomp=DECOMP 17 | Decomposition file 18 | 19 | -------------------------------------------------------------------------------- /output_processing/decomposition_fields/decomposition_fields.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys, os, glob, shutil, numpy, math 3 | 4 | from netCDF4 import * 5 | from netCDF4 import Dataset as NetCDFFile 6 | from pylab import * 7 | 8 | import matplotlib 9 | import matplotlib.pyplot as plt 10 | 11 | from optparse import OptionParser 12 | 13 | parser = OptionParser() 14 | parser.add_option("-f", "--file", dest="filename", help="Path to grid file", metavar="FILE") 15 | parser.add_option("-d", "--decomp", dest="decomposition", help="Decomposition file", metavar="DECOMP") 16 | 17 | options, args = parser.parse_args() 18 | 19 | if not options.filename: 20 | parser.error("A grid file is required.") 21 | 22 | if not options.decomposition: 23 | parser.error("A decomposition file is required.") 24 | 25 | grid = NetCDFFile(options.filename, 'a') 26 | 27 | nCells = len(grid.dimensions['nCells']) 28 | nEdges = len(grid.dimensions['nEdges']) 29 | nVertices = len(grid.dimensions['nVertices']) 30 | vertexDegree = len(grid.dimensions['vertexDegree']) 31 | 32 | cellsOnEdge_full = grid.variables['cellsOnEdge'][:] -1 33 | cellsOnVertex_full = grid.variables['cellsOnVertex'][:] -1 34 | 35 | try: 36 | cellDecomposition_full = grid.createVariable('cellDecompositon', 'i4', ( 'nCells' ,) ) 37 | except: 38 | cellDecomposition_full = grid.variables['cellDecompositon'] 39 | 40 | try: 41 | triangleDecomposition_full = grid.createVariable('triangleDecomposition', 'i4', ( 'nVertices' ,) ) 42 | except: 43 | triangleDecomposition_full = grid.variables['triangleDecomposition'] 44 | 45 | try: 46 | edgeDecomposition_full = grid.createVariable('edgeDecomposition', 'i4', ( 'nEdges', ) ) 47 | except: 48 | edgeDecomposition_full = grid.variables['edgeDecomposition'] 49 | 50 | print 'Reading decomposition file' 51 | i = 0 52 | decomp_file = open(options.decomposition, 'r') 53 | for block in iter(lambda: decomp_file.readline(), ""): 54 | block_arr = block.split() 55 | cellDecomposition_full[i] = int(block_arr[0]) 56 | i = i + 1 57 | 58 | decomp_file.close() 59 | 60 | print 'Computing vertex owner' 61 | for i in arange(0, nVertices): 62 | owner = cellDecomposition_full[cellsOnVertex_full[i][0]] 63 | 64 | triangleDecomposition_full[i] = owner 65 | 66 | print 'Computing edge owner' 67 | for i in arange(0, nEdges): 68 | owner = cellDecomposition_full[cellsOnEdge_full[i][0]] 69 | 70 | edgeDecomposition_full[i] = owner 71 | 72 | grid.close() 73 | -------------------------------------------------------------------------------- /output_processing/grid_quality/README: -------------------------------------------------------------------------------- 1 | Author: Doug Jacobsen 2 | Date: 02/12/13 3 | 4 | About: 5 | This script is used to compute quality metrics on an MPAS mesh. 6 | It appends to the grid file four arrays. 7 | cellQuality 8 | triangleQuality 9 | triangleAngleQuality 10 | obtuseTriangle 11 | 12 | In addition, it writes histgrams to a file named quality.png, and potentially displays them. 13 | 14 | The usage statement can be seen with ./grid_quality.py -h, but is as follows. 15 | 16 | Usage: grid_quality.py [options] 17 | 18 | Options: 19 | -h, --help show this help message and exit 20 | -f FILE, --file=FILE Path to grid file 21 | -b NUMBINS, --bins=NUMBINS 22 | Number of bins for histogram 23 | -q, --quiet Turns off display of plots, though they are still 24 | saved in quality.png 25 | 26 | -------------------------------------------------------------------------------- /seaice/README: -------------------------------------------------------------------------------- 1 | Readme file for MPAS-Tools seaice directory. 2 | -------------------------------------------------------------------------------- /visualization/mpas_draw/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore execuable 2 | MpasDraw.x 3 | -------------------------------------------------------------------------------- /visualization/mpas_draw/Makefile: -------------------------------------------------------------------------------- 1 | CXX=g++ 2 | #CXXFLAGS= -O3 3 | CXXFLAGS= -O3 -m64 4 | #NETCDF=/opt/netcdf/3.6.3/64 5 | 6 | DBGFLAGS= -g -m64 7 | 8 | #OFFSETFLAG=-D_64BITOFFSET 9 | 10 | platform=$(shell uname) 11 | ifeq ($(platform),Darwin) 12 | PLATFORM=_MACOS 13 | else 14 | PLATFORM=_LINUX 15 | endif 16 | 17 | ifeq ($(PLATFORM),_LINUX) 18 | CXXLIBS = -I$(NETCDF)/include -L$(NETCDF)/lib -lGL -lglut -lnetcdf_c++ -lnetcdf -lGLU -lstdc++ 19 | endif 20 | 21 | ifeq ($(PLATFORM),_MACOS) 22 | CXXLIBS = -L$(NETCDF)/lib -lnetcdf -lnetcdf_c++ -I$(NETCDF)/include -lstdc++ -framework OpenGL -framework GLUT 23 | endif 24 | 25 | all: 26 | $(CXX) mpas_draw.cpp vec_utils.cpp netcdf_utils.cpp $(CXXLIBS) $(CXXFLAGS) $(OFFSETFLAG) -D$(PLATFORM) -o MpasDraw.x 27 | 28 | debug: 29 | $(CXX) mpas_draw.cpp vec_utils.cpp netcdf_utils.cpp $(CXXLIBS) $(DBGFLAGS) $(OFFSETFLAG) -D$(PLATFORM) -o MpasDraw.x 30 | 31 | clean: 32 | rm MpasDraw.x 33 | 34 | -------------------------------------------------------------------------------- /visualization/mpas_draw/constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * constants.h 3 | * vordraw 4 | * 5 | * Created by Geoffrey Womeldorff on 3/30/09. 6 | * Copyright 2009 FSU. All rights reserved. 7 | * 8 | */ 9 | 10 | #define kWindowWidth 400 11 | #define kWindowHeight 400 12 | #define KEY_ESCAPE 27 13 | 14 | #define KEY_A 65 15 | #define KEY_B 66 16 | #define KEY_C 67 17 | #define KEY_D 68 18 | #define KEY_E 69 19 | #define KEY_F 70 20 | #define KEY_G 71 21 | #define KEY_H 72 22 | #define KEY_I 73 23 | #define KEY_J 74 24 | #define KEY_K 75 25 | #define KEY_L 76 26 | #define KEY_M 77 27 | #define KEY_N 78 28 | #define KEY_O 79 29 | #define KEY_P 80 30 | #define KEY_Q 81 31 | #define KEY_R 82 32 | #define KEY_S 83 33 | #define KEY_T 84 34 | #define KEY_U 85 35 | #define KEY_V 86 36 | #define KEY_W 87 37 | #define KEY_X 88 38 | #define KEY_Y 89 39 | #define KEY_Z 90 40 | 41 | #define KEY_a 97 42 | #define KEY_b 98 43 | #define KEY_c 99 44 | #define KEY_d 100 45 | #define KEY_e 101 46 | #define KEY_f 102 47 | #define KEY_g 103 48 | #define KEY_h 104 49 | #define KEY_i 105 50 | #define KEY_j 106 51 | #define KEY_k 107 52 | #define KEY_l 108 53 | #define KEY_m 109 54 | #define KEY_n 110 55 | #define KEY_o 111 56 | #define KEY_p 112 57 | #define KEY_q 113 58 | #define KEY_r 114 59 | #define KEY_s 115 60 | #define KEY_t 116 61 | #define KEY_u 117 62 | #define KEY_v 118 63 | #define KEY_w 119 64 | #define KEY_x 120 65 | #define KEY_y 121 66 | #define KEY_z 122 67 | 68 | #define KEY_0 48 69 | #define KEY_1 49 70 | #define KEY_2 50 71 | #define KEY_3 51 72 | #define KEY_4 52 73 | #define KEY_5 53 74 | #define KEY_6 54 75 | #define KEY_7 55 76 | #define KEY_8 56 77 | #define KEY_9 57 78 | 79 | #define KEY_COMMA 44 80 | #define KEY_PERIOD 46 81 | 82 | #define COLORS 16 83 | #define PENTA_R 0.1 84 | #define PENTA_G 0.1 85 | #define PENTA_B 0.5 86 | #define HEXA_R 0.0 87 | #define HEXA_G 1.0 88 | #define HEXA_B 0.0 89 | #define HEPTA_R 0.9 90 | #define HEPTA_G 0.0 91 | #define HEPTA_B 0.1 92 | #define OTHER_R 1.0 93 | #define OTHER_G 0.32549019608 94 | #define OTHER_B 0.2 95 | #define LIL_R 0.25882352941 96 | #define LIL_G 0.75294117647 97 | #define LIL_B 0.98431372549 98 | 99 | #define LINE_R 0.0 100 | #define LINE_G 0.0 101 | #define LINE_B 0.0 102 | 103 | #define REGL_R 0.0 104 | #define REGL_G 0.0 105 | #define REGL_B 0.0 106 | 107 | #define REG_R 1.0 108 | #define REG_G 0.0 109 | #define REG_B 0.0 110 | 111 | #define PI_DP 3.141592653589793 112 | -------------------------------------------------------------------------------- /visualization/mpas_draw/netcdf_utils.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | bool netcdf_mpas_read_onsphere(string filename); 5 | double netcdf_mpas_read_sphereradius(string filename); 6 | int netcdf_mpas_read_dim ( string filename, string dim_name ); 7 | int netcdf_mpas_read_num_vars(string filename); 8 | void netcdf_mpas_read_xyzcell ( string filename, int ncells, double xcell[], double ycell[], double zcell[] ); 9 | void netcdf_mpas_read_xyzvertex ( string filename, int nvertices, double xvertex[], double yvertex[], double zvertex[] ); 10 | void netcdf_mpas_read_xyzedge ( string filename, int nedges, double xedge[], double yedge[], double zedge[] ); 11 | void netcdf_mpas_read_verticesoncell ( string filename, int maxedges, int ncells, int verticesOnCell[] ); 12 | void netcdf_mpas_read_verticesonedge ( string filename, int nedges, int verticesonedge[] ); 13 | void netcdf_mpas_read_cellsonvertex ( string filename, int nvertices, int cellsonvertex[] ); 14 | void netcdf_mpas_read_cellsonedge ( string filename, int nedges, int cellsonedge[] ); 15 | void netcdf_mpas_read_nedgesoncell ( string filename, int ncells, int nedgesoncell[] ); 16 | int netcdf_mpas_list_ncell_fields(string filename); 17 | int netcdf_mpas_list_nvertex_fields(string filename); 18 | int netcdf_mpas_list_nedge_fields(string filename); 19 | int netcdf_mpas_field_num_dims(string filename, int id); 20 | int netcdf_mpas_field_num_items(string filename, int id); 21 | void netcdf_mpas_print_field_info(string filename, int id); 22 | void netcdf_mpas_read_field(string filename, int id, double values[], int cur_time, int cur_level); 23 | void netcdf_mpas_read_full_field(string filename, int id, double values[]); 24 | int netcdf_mpas_get_vert_dim_info(string filename, int id, int& dim_size, string& dim_name); 25 | int netcdf_mpas_get_xtime(string filename, int cur_time, char *xtime); 26 | -------------------------------------------------------------------------------- /visualization/mpas_draw/vec_utils.h: -------------------------------------------------------------------------------- 1 | using namespace std; 2 | 3 | double r8_huge ( ); 4 | double r8vec_max ( int n, double r8vec[], double missing_value ); 5 | double r8vec_min ( int n, double r8vec[], double missing_value ); 6 | void r8vec_min_max ( int n, double r8vec[], double &min, double&max, double missing_value ); 7 | -------------------------------------------------------------------------------- /visualization/paraview_vtk_field_extractor/add_earth_sphere.py: -------------------------------------------------------------------------------- 1 | """ 2 | A macro for adding an opaque sphere just under MPAS paraview data on the 3 | sphere. 4 | 5 | Add to ParaView via Macros -> Add new macro.. 6 | 7 | Apply by selecting the imported pdv file in the pipeline browser, then running 8 | Macros -> add_earth_sphere 9 | 10 | Xylar Asay-Davis 11 | 24-Aug-2017 12 | """ 13 | import paraview.simple 14 | 15 | 16 | # disable automatic camera reset on 'Show' 17 | paraview.simple._DisableFirstRenderCameraReset() 18 | 19 | # find view 20 | renderView1 = paraview.simple.GetActiveView() 21 | 22 | # create a new 'Sphere' 23 | sphere1 = paraview.simple.Sphere() 24 | sphere1.Radius = 6369000.0 25 | sphere1.ThetaResolution = 1000 26 | sphere1.PhiResolution = 1000 27 | 28 | # show data from sphere1 29 | sphere1Display = paraview.simple.Show(sphere1, renderView1) 30 | -------------------------------------------------------------------------------- /visualization/paraview_vtk_field_extractor/annotate_date.py: -------------------------------------------------------------------------------- 1 | """ 2 | A macro for annotating with YYYY-MM-DD based on time values that are assumed 3 | to be years since 0000-01-01. 4 | 5 | Add to ParaView via Macros -> Add new macro.. 6 | 7 | Apply by selecting the imported pdv file in the pipeline browser, then running 8 | Macros -> annotate_date 9 | 10 | Xylar Asay-Davis 11 | 24-Aug-2017 12 | """ 13 | 14 | # import the simple module from the paraview 15 | import paraview.simple 16 | 17 | # disable automatic camera reset on 'Show' 18 | paraview.simple._DisableFirstRenderCameraReset() 19 | 20 | # find source 21 | source = paraview.simple.GetActiveSource() 22 | 23 | # create a new 'Programmable Filter' 24 | programmableFilter1 = \ 25 | paraview.simple.ProgrammableFilter(Input=source) 26 | programmableFilter1.OutputDataSetType = 'vtkTable' 27 | programmableFilter1.Script = \ 28 | 'from paraview.simple import GetAnimationScene\n' \ 29 | 'import numpy\n' \ 30 | '\n' \ 31 | 'daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]\n' \ 32 | 'cumSumDays = numpy.append([0], numpy.cumsum(daysInMonth))\n' \ 33 | '\n' \ 34 | 't = GetAnimationScene().TimeKeeper.Time\n' \ 35 | 'days = int(365.*t+0.5)\n' \ 36 | 'year = int(days/365.)\n' \ 37 | 'days -= 365*year\n' \ 38 | 'index = numpy.nonzero(days < cumSumDays)[0][0]\n' \ 39 | 'month = index\n' \ 40 | 'days = days - cumSumDays[index-1]\n' \ 41 | 'day = days+1\n' \ 42 | '\n' \ 43 | 'datetime = \'{:04d}-{:02d}-{:02d}\'.format(year, month, day)\n' \ 44 | '\n' \ 45 | 'outputarray = vtk.vtkStringArray()\n' \ 46 | 'outputarray.SetName("datetime")\n' \ 47 | 'outputarray.SetNumberOfTuples(1)\n' \ 48 | 'outputarray.SetValue(0, "{}".format(datetime))\n' \ 49 | 'output.RowData.AddArray(outputarray)' 50 | programmableFilter1.RequestInformationScript = '' 51 | programmableFilter1.RequestUpdateExtentScript = '' 52 | programmableFilter1.PythonPath = '' 53 | 54 | # create a new 'Python Annotation' 55 | pythonAnnotation1 = paraview.simple.PythonAnnotation(Input=programmableFilter1) 56 | pythonAnnotation1.ArrayAssociation = 'Field Data' 57 | pythonAnnotation1.Expression = \ 58 | '"{}".format(input.RowData["datetime"].GetValue(0))' 59 | 60 | # find view 61 | renderView1 = paraview.simple.GetActiveView() 62 | # show data in view 63 | pythonAnnotation1Display = paraview.simple.Show(pythonAnnotation1, renderView1) 64 | pythonAnnotation1Display.FontSize = 12 65 | # update the view to ensure updated data information 66 | renderView1.Update() 67 | 68 | -------------------------------------------------------------------------------- /visualization/paraview_vtk_field_extractor/mpas_tools: -------------------------------------------------------------------------------- 1 | ../../conda_package/mpas_tools/ --------------------------------------------------------------------------------